Java开发从入门到精通(二十):Java的面向对象编程OOP:Collection集合框架

news2024/12/25 0:21:35

Java大数据开发和安全开发

  • (一)Java的集合进阶
    • 1.1 集合体系结构
    • 1.2 Collection集合
      • 1.2.1 Collection集合包含哪些接口和实现类
      • 1.2.2 Collection集合特点
      • 1.2.3 为啥要先学Collection的常用方法?
      • 1.2.4 Collection集合的遍历
        • 1.2.4.1 迭代器
          • 1.2.4.1.1 迭代器概述
          • 1.2.4.1.2 Collection集合获取迭代器的方法
        • 1.2.4.2 增强for
        • 1.2.4.3 Lambvda表达式
          • 1.2.4.3.1 Lambda表达式遍历集合
      • 1.2.5 Collection集合案例演示
    • 1.3 List集合
      • 1.3.1 List集合的特有方法
      • 1.3.2 List集合的遍历
      • 1.3.3 Arraylist集合
      • 1.3.4 Linkedlist集合
        • 1.3.4.1 单链表
        • 1.3.4.2 双链表
        • 1.3.4.3 LinkedList特有方法
    • 1.4 Set集合
      • 1.4.1 Hashset集合的底层原理
        • 1.4.1.1 哈希值的概念
        • 1.4.1.2 Hashset集合的底层原理
          • 1.4.1.1.1 JDK8之前,哈希表=`数组+链表 `
          • 1.4.1.1.2 JDK8开始,哈希表=`数组+链表+红黑树`
          • 1.4.1.1.3 数据结构
            • 1.4.1.1.3.1 普通二叉树
            • 1.4.1.1.3.2 二叉查找树
            • 1.4.1.1.3.3 平衡二叉树
            • 1.4.1.1.3.4 自平衡的二叉树 红黑树
        • 1.4.1.3 深入理解Hashset集合去重复的机制。
      • 1.4.2 LinkedHashSet集合
      • 1.4.2 TreeSet集合
        • 1.4.2.1 自定义排序规则
          • 1.4.2.1.1 方式一
          • 1.4.2.1.2 方式二
    • 1.5 Collection集合的使用场景

(一)Java的集合进阶

1.1 集合体系结构

为了应对不同的场景需要,所以提供很多集合,总体来说分成单列集合和双列集合
在这里插入图片描述

1.2 Collection集合

1.2.1 Collection集合包含哪些接口和实现类

  • 包含list接口和set接口
  • 包含Arraylist linkedlist hashset treeset实现类

在这里插入图片描述

1.2.2 Collection集合特点

  • List系列集合:添加的元素是有序、可重复、有索引
    • ArrayList、LinekdList:有序、可重复、有索引。
  • set系列集合:添加的元素是无序、不重复、无索引
    • Hashset:无序、不重复、无索引:
    • LinkedHashset:有序、不重复、无索引。
    • TreeSet:按照大小默认升序排序、不重复、无索引。

1.2.3 为啥要先学Collection的常用方法?

  • Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的。

在这里插入图片描述

  • 以下是Collection的常用方法代码示例
package com.qianxin.jihekuangjia;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class Test1 {
    public static void main(String[] args) {
        Collection<String> c= new ArrayList<>();// 多态写法
        //1.public boolean add(E e):添加元素,添加成功返回true。
        c.add("java1");
        c.add("java1");
        c.add("java2");
        c.add("java2");
        c.add("java3");
        System.out.println(c);

        // 2.public void clear():清空集合的元素,
        c.clear();
        System.out.println(c);

        //3.public boolean isEmpty():判断集合是否为空 是空返回true,反之
        System.out.println(c.isEmpty());//true

        // 4.public int size():获取集合的大小。
        System.out.println(c.size());

        //5.public boolean contains(0bject obj):判断集合中是否包含某个元素
        System.out.println(c.contains("java1"));// true
        System.out.println(c.contains("Java1"));// false

        //6.public boolean remove(E e):删除某个元素:如果有多个重复元素默认删除前面的第一个!
        System.out.println(c.remove( "java1"));
        System.out.println(c);

        //7.public 0bject[]toArray():把集合转换成数组
        Object[] arr = c.toArray();
        System.out.println(Arrays.toString(arr));

        String[]arr2 =c.toArray(new String[c.size()]);
        System.out.println(Arrays.toString(arr2));


        // 把一个集合的全部数据倒入到另一个集合中去。
        Collection<String>c1 = new ArrayList<>();c1.add("java1");
        c1.add("java2");
        Collection<String>c2 =new ArrayList<>();
        c2.add("java3");
        c2.add("java4");
        c1.addAll(c2);//就是把c2集合的全部数据倒入到c1集合中去。
        System.out.println(c1);

    }
}

1.2.4 Collection集合的遍历

1.2.4.1 迭代器
1.2.4.1.1 迭代器概述

迭代器是用来遍历集合的专用方式(数组没有迭代器),在ava中迭代器的代表是Iterator。

1.2.4.1.2 Collection集合获取迭代器的方法

Collection获取迭代器的方法
在这里插入图片描述

Iterator迭代器中的常用方法

在这里插入图片描述

Iterator迭代器的使用

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**大
 目标:Collection集合的遍历方式一:使迭代器Iterator遍历
 **/
public class Test {
    public static void main(String[] args) {

        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("索素");
        c.add("灭绝");
        System.out.println(c);
        //c=[赵敏,小昭,素素,灭绝]
        //使用迭代器遍历集合
        // 使用迭代器遍历集合
        // 1、从集合对象中获取迭代器对象。
        Iterator<String> it = c.iterator();
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());
        System.out.println(it.next());// 出现异常的

        // 2、我们应该使用循环结合迭代器遍历集合。
        while(it.hasNext()) {
            String ele = it.next();
            System.out.println(ele);
        }
    }
}
[赵敏, 小昭, 索素, 灭绝]
赵敏
小昭
索素
灭绝
1.2.4.2 增强for
  • 增强for可以用来遍历集合或者数组。
  • 增强for遍历集合,本质就是迭代器遍历集合的简化写法。

在这里插入图片描述

在这里插入图片描述
增强for遍历集合代码示例

import java.util.ArrayList;
import java.util.Collection;
public class Test {
    public static void main(String[] args) {

        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("索素");
        c.add("灭绝");
        System.out.println(c);
        //c=[赵敏,小昭,素素,灭绝]
        
        // 使用增强for遍历集合或者数组、ele这个可以随意写 类似python的for iter in list  ele等同于iter
        for(String ele :c){
            System.out.println(ele);
        }
        String[] names ={"迪丽热巴","古力娜扎","稀奇哈哈"};
        for(String name :names) {
            System.out.println(name);
        }
    }
}
1.2.4.3 Lambvda表达式
1.2.4.3.1 Lambda表达式遍历集合

得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的方式来遍历集合。

  • 需要使用Collection的如下方法来完成

在这里插入图片描述

Lambda表达式遍历集合代码示例

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class Test {
    public static void main(String[] args) {

        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("索素");
        c.add("灭绝");
        System.out.println(c);
        //c=[赵敏,小昭,素素,灭绝]

        // default void forEach(Consumer<? super T> action):结合Lambda表达式遍历集合
        c.forEach(new Consumer<String>(){
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
    });
    }
}

[赵敏, 小昭, 索素, 灭绝]
赵敏
小昭
索素
灭绝

但是上面代码还可以进行如下简化过程

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class Test {
    public static void main(String[] args) {

        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("索素");
        c.add("灭绝");
        System.out.println(c);
        //c=[赵敏,小昭,素素,灭绝]

        // default void forEach(Consumer<? super T> action):结合Lambda表达式遍历集合
        c.forEach(new Consumer<String>(){
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
    });
        c.forEach((String s)->{
            System.out.println(s);
        });

        c.forEach(s->{
            System.out.println(s);
    });

        c.forEach(s -> System.out.println(s));
        //最终简化的代码如下
        c.forEach(System.out::println);

    }
}

最终代码变成

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class Test {
    public static void main(String[] args) {
        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("索素");
        c.add("灭绝");
        System.out.println(c);
        //c=[赵敏,小昭,素素,灭绝]

        // default void forEach(Consumer<? super T> action):结合Lambda表达式遍历集合
        //最终简化的代码如下
        c.forEach(System.out::println);
    }
}

在这里插入图片描述

1.2.5 Collection集合案例演示

需求

  • 展示多部电影信息。

分析

  • 每部电影都是一个对象,多部电影要使用集合装起来,

  • 遍历集合中的3个电影对象,输出每部电影的详情信息,
    在这里插入图片描述

电影循环展示代码示例

package com.qianxin.jihekuangjia;

import java.util.ArrayList;
import java.util.Collection;

public class SystemDemo {
    public static void main(String[] args) {
        Collection<Movie> movies = new ArrayList<>();
        movies.add(new Movie("《肖生克的救赎》",9.7,"罗宾斯"));
        movies.add(new Movie("《霸王别姬》",9.6,"张国荣、张丰毅"));
        movies.add(new Movie("《阿甘正传》",9.5,"汤姆.汉克斯"));
        System.out.println(movies); //输出的是对象的内存地址 需要改写toString方法

        for(Movie movie :movies) {
            System.out.println("电影名:" + movie.getName());
            System.out.println("评分:" + movie.getScore());
            System.out.println("主演:" + movie.getAcotr());
            System.out.println("------------------------------------");
        }
    }
}
public class Movie {
    private String name;
    private double score;
    private String acotr;
    
    public Movie() {
    }

    public Movie(String name, double score, String acotr) {
        this.name = name;
        this.score = score;
        this.acotr = acotr;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public String getAcotr() {
        return acotr;
    }

    public void setAcotr(String acotr) {
        this.acotr = acotr;
    }

    @Override
    public String toString() {
        return "Movie{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", acotr='" + acotr + '\'' +
                '}';
    }
}

1.3 List集合

1.3.1 List集合的特有方法

List集合因为支持索引,所以多了很多与索引相关的方法,当然,Collection的功能List也都继承了。
在这里插入图片描述

import java.util.ArrayList;
import java.util.List;

public class ListTest {
    public static void main(String[] args) {
        //1.创建一个ArrayList集合对象(有序、可重复、有索引)
        List<String> list = new ArrayList<>();// 一行经典代码
        list.add("蜘蛛精");
        list.add("至尊宝");
        list.add("至尊宝");
        list.add("牛夫人");
        System.out.println(list);//[蜘蛛精,至尊宝,至尊宝,牛夫人]

        //2.public void add(int index,E element):在某个索引位置插入元素。
        list.add( 2, "紫霞仙子");
        System.out.println(list);

        // 3.public E remove(int index):根据索引删除元素,返回被删除元素
        System.out.println(list.remove(2));
        System.out.println(list);

        // 4.public E get(int index):返回集合中指定位置的元素。
        System.out.println(list.get(3));

        // 5.public E set(int index,E element): 修改索引位置处的元素,修改成功后,会返回原来的数据
        System.out.println(list.set(3,"牛魔王"));
        System.out.println(list);
    }
}

1.3.2 List集合的遍历

  • for循环(因为List集合有索引)
  • 迭代器
  • 增强for循环
  • Lambda表达式
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("糖宝宝");
        list.add("蜘蛛精");
        list.add("至尊宝");

        //for循环

        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i);
            System.out.println(name);
        }
        //迭代器
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        
        //lambda表达式
        list.forEach(System.out::println);
        //增加for
        
        for (String s : list) {
            System.out.println(s);

        }
    }
}

1.3.3 Arraylist集合

  • ArrayList:有序,可重复,有索引。
  • LinkedList:有序,可重复,有索引。

两者的区别

  • 底层采用的数据结构不同,应用场景不同
  • 数据结构指的是存储、组织数据的方式

ArrayList集合的底层原理

  • 基于数组实现的。

在这里插入图片描述

  • 查询速度快(注意:是根据索引查询数据快):查询数据通过地址值和索引定位,查询任意数据耗时相同。
  • 删除效率低:可能需要把后面很多的数据进行前移
  • 添加效率极低:可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组的扩容。

利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
添加第一个元素时,底层会创建一个新的长度为10的数组
存满时,会扩容1.5倍
在这里插入图片描述
ArrayList集合适合的应用场景
1、ArrayList适合:根据索引查询数据比如根据随机索引取数据(高效)!或者数据量不是很大时!
2、ArrayList不适合:数据量大的同时,又要频繁的进行增删操作!

1.3.4 Linkedlist集合

LinkedList集合的底层原理

  • 基于双链表实现的
1.3.4.1 单链表
  • 链表的特点1: 查询慢,无论查询哪个数据都要从头开始找
  • 链表的特点2: 链表增删相对快

在这里插入图片描述

  • 链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址
    在这里插入图片描述
    在这里插入图片描述
1.3.4.2 双链表
  • 特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的。

在这里插入图片描述

1.3.4.3 LinkedList特有方法

LinkedList新增了:很多首尾操作的特有方法。
在这里插入图片描述

LinkedList的应用场景之一:可以用来设计队列

  • 是在首尾增删元素,用Linkecllist来实现很合适!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.LinkedList;
public class LinkedListTest {
    public static void main(String[] args) {
        // 1、创建一个队列。
        LinkedList<String> queue = new LinkedList<>();
        // 入队
        queue.addLast("第1号人");
        queue.addLast("第2号人");
        queue.addLast("第3号人");
        queue.addLast("第4号人");
        System.out.println(queue);

        // 出队
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);
    }
}
[1号人,2号人,3号人,4号人]1号人
第2号人
第3号人
[4号人]

LinkedList的应用场景之一:可以用来设计栈

  • 只是在首部增删元素,用LinkeclList来实现很合适!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import java.util.LinkedList;
public class LinkedListTest {
    public static void main(String[] args) {
        // 2、创建一个栈对象。
        LinkedList<String> stack = new LinkedList<>();
        // 压栈
        stack.addFirst("第1颗子弹");
        stack.addFirst("第2颗子弹");
        stack.addFirst("第3颗子弹");
        stack.addFirst("第4颗子弹");
        System.out.println(stack);
        // 出栈
        System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());
        System.out.println(stack);
    }
}
[4颗子弹,3颗子弹,2颗子弹,1颗子弹]4颗子弹
第3颗子弹
[2颗子弹,1颗子弹]

addFirst 等价于 push压栈
removeFirst 等价于 pop出栈

import java.util.LinkedList;
public class LinkedListTest {
    public static void main(String[] args) {
		// 2、创建一个栈对象。
        LinkedList<String> stack = new LinkedList<>();
        // 压栈
        stack.push("第1颗子弹");
        stack.push("第2颗子弹");
        stack.push("第3颗子弹");
        stack.push("第4颗子弹");
        System.out.println(stack);
        // 出栈
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack);
    }
}
[4颗子弹,3颗子弹,2颗子弹,1颗子弹]4颗子弹
第3颗子弹
[2颗子弹,1颗子弹]

1.4 Set集合

Set系列集合特点:无序:添加数据的顺序和获取出的数据顺序不一致; 无索引; 不重复:

  • Hashset:无序、不重复、无索引。
  • LinkedHashSet:有序、不重复、无索引。
  • Treeset:排序、不重复、无索引。
import java.util.HashSet;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        //1、创建一个Set集合的对象
        Set<Integer> set = new HashSet<>();// 创建了一个HashSet的集合对象。一行经典代码 无序不重复 无索引        
        set.add(666);
        set.add(555);
        set.add(555);
        set.add(888);
        set.add(888);
        set.add(777);
        set.add(777);

        System.out.println(set);
    }
}
[888, 777, 666, 555]
import java.util.LinkedHashSet;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        //1、创建一个Set集合的对象
        Set<Integer> set = new LinkedHashSet<>();//有序 不重复 无索引
        set.add(666);
        set.add(555);
        set.add(555);
        set.add(888);
        set.add(888);
        set.add(777);
        set.add(777);

        System.out.println(set);
    }
}
[666, 555, 888, 777]
import java.util.Set;
import java.util.TreeSet;

public class SetTest {
    public static void main(String[] args) {
        //1、创建一个Set集合的对象
        Set<Integer>set=new TreeSet<>();// 可排序(升序)不重复 无索引
        set.add(666);
        set.add(555);
        set.add(555);
        set.add(888);
        set.add(888);
        set.add(777);
        set.add(777);

        System.out.println(set);
    }
}
[555, 666, 777, 888]

注意:
Set要用到的常用方法,基本上就是collection提供的!!
自己几乎没有额外新增一些常用功能!

1.4.1 Hashset集合的底层原理

1、为什么添加的元素无序、不重复、无索引?
2、增删改查数据有什么特点,适合什么场景?

1.4.1.1 哈希值的概念
  • 就是一个int类型的数值,Java中每个对象都有一个哈希值。
  • Java中的所有对象,都可以调用0bejct类提供的hashCode方法,返回该对象自己的哈希值。
  • public int hashCode():返回对象的哈希码值。

对象哈希值的特点

  • 同一个对象多次调用hashcode()方法返回的哈希值是相同的。
  • 不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞),极少数会相同
    在这里插入图片描述
public class Student {
    private String name;
    private int age;
    private double height;

    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
}
public class SetTest1 {

    public static void main(String[] args) {
        Student s1 = new Student( "蜘蛛精",25,169.5);
        Student s2 =new Student( "紫霞",22,166.5);
        System.out.println(s1.hashCode());
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());


        String str1 = new String( "abc");
        String str2 = new String( "acD");
        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());
    }
}
1163157884
1163157884
1956725890
96354
96354
1.4.1.2 Hashset集合的底层原理
  • 基于哈希表实现。
  • 哈希表是一种增删改查数据,性能都较好的数据结构

哈希表

  • JDK8之前,哈希表=数组+链表
  • JDK8开始,哈希表=数组+链表+红黑树
1.4.1.1.1 JDK8之前,哈希表=数组+链表
  • hashSet在第一次添加数据时会创建一个默认长度16的数组,默认加载因子为0.75,数组名table

在这里插入图片描述
在这里插入图片描述
假如添加的元素是166 余数是1 那就放在1的位置 如果还有余数是1的就挂在166元素的下面
在这里插入图片描述
这就是为什么hashset添加的元素无序 不重复、无索引的原因
哈希表是一种增删改查数据性能都较好的结构

1、如果数组快占满了,会出什么问题?该咋办?
链表会过长,导致查询性能降低
扩容

1.4.1.1.2 JDK8开始,哈希表=数组+链表+红黑树

在这里插入图片描述

1.4.1.1.3 数据结构
1.4.1.1.3.1 普通二叉树

一个节点包括父节点地址 -》值-》左子节点地址-》右子节点地址
在这里插入图片描述
在这里插入图片描述
普通二叉树
没有意义 但是二叉查找树遵循二分法
在这里插入图片描述

1.4.1.1.3.2 二叉查找树

存在的问题:当数据已经是排好序的,导致查询的性能与单链表一样,查询速度变慢!
在这里插入图片描述

1.4.1.1.3.3 平衡二叉树

在这里插入图片描述

1.4.1.1.3.4 自平衡的二叉树 红黑树

在这里插入图片描述

1.4.1.3 深入理解Hashset集合去重复的机制。

Hashset集合默认不能对内容一样的两个不同对象去重复!
比如内容一样的两个学生对象存入到HashSet集合中去,Hashset集合是不能去重复的!

import java.util.HashSet;
import java.util.Set;

public class SetTest1 {

    public static void main(String[] args) {
        Set<Student> students =new HashSet<>();
        Student s1 = new Student("至尊宝",28,169.6);
        Student s2 = new Student("蜘蛛精",23,169.6);
        Student s3 = new Student("蜘蛛精",23,169.6);
        Student s4=new Student( "牛魔王",48,169.6);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        System.out.println(students);
    }
}

1.4.2 LinkedHashSet集合

LinkedHashset:有序、不重复、无索引

import java.util.LinkedHashSet;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        //1、创建一个Set集合的对象
        Set<Integer> set = new LinkedHashSet<>();//有序 不重复 无索引
        set.add(666);
        set.add(555);
        set.add(555);
        set.add(888);
        set.add(888);
        set.add(777);
        set.add(777);

        System.out.println(set);
    }
}
[666555888777]

LinkedHashset底层原理

  • 依然是基于哈希表(数组、链表、红黑树)实现的。
  • 但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。

假如元素的hash求余得到的是8,那么这个元素将放在下标为八的位置
在这里插入图片描述在这里插入图片描述

1.4.2 TreeSet集合

  • 特点:不重复、无索引 可排序
  • 默认升序排序按照元素的大小,由小到大排序)
  • 底层是基于红黑树实现的排序。
import java.util.Set;
import java.util.TreeSet;

public class SetTest1 {

    public static void main(String[] args) {
        Set<Integer>set1 = new TreeSet<>();
        set1.add(6);
        set1.add(5);
        set1.add(5);
        set1.add(7);
        System.out.println(set1);
    }
}
[5, 6, 7]

注意:
对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Student对象,Treeset默认是无法直接排序的,

TreeSet是一定会给集合排序的 不知道怎么排序的就会直接报错

import java.util.Set;
import java.util.TreeSet;

public class SetTest1 {

    public static void main(String[] args) {
        Set<Student> students =new TreeSet<>();
        Student s1 = new Student("至尊宝",28,169.6);
        Student s2 = new Student("蜘蛛精",23,169.6);
        Student s3 = new Student("蜘蛛精",23,169.6);
        Student s4=new Student( "牛魔王",48,169.6);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        System.out.println(students);
    }
}
1.4.2.1 自定义排序规则

TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。

1.4.2.1.1 方式一

让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    private double height;

    @Override
    public int compareTo(Student o) {

        // 如果认为左边对象大于右边对象返回正整数
        // 如果认为左边对象小于右边对象返回负整数
        // 如果认为左边对象等于右边对象返回0
        // 需求:按照年龄升序排序、

        return this.age-o.age;
    }

    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}
import java.util.Set;
import java.util.TreeSet;

public class SetTest1 {

    public static void main(String[] args) {
        Set<Student> students =new TreeSet<>();
        Student s1 = new Student("至尊宝",28,169.6);
        Student s2 = new Student("蜘蛛精",23,169.6);
        Student s3 = new Student("蜘蛛精",23,169.6);
        Student s4=new Student( "牛魔王",48,169.6);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        System.out.println(students);
    }
}

按照年龄升序排列

[Student{name='蜘蛛精', age=23, height=169.6}, Student{name='至尊宝', age=28, height=169.6}, Student{name='牛魔王', age=48, height=169.6}]
1.4.2.1.2 方式二

◎通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则。
public TreeSet(Comparator<?super E> comparator)

import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class SetTest1 {

    public static void main(String[] args) {
        //就近选择自己自带的比较器对象进行排序
        Set<Student> students =new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //需求:按照身高升序排序
                return Double.compare(o1.getHeight(),o2.getHeight());
            }
        });
        Student s1 = new Student("至尊宝",28,169.6);
        Student s2 = new Student("蜘蛛精",23,169.6);
        Student s3 = new Student("蜘蛛精",23,169.6);
        Student s4=new Student( "牛魔王",48,169.6);
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        System.out.println(students);
    }
}

简化写法

//就近选择自己自带的比较器对象进行排序
   Set<Student> students =new TreeSet<>((o1, o2) -> Double.compare(o1.getHeight(),o2.getHeight()));

1.5 Collection集合的使用场景

  • 1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
    • 用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)
  • 2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
    • 用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的。
  • 3.如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
    • 用Hashset集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)
  • 4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
    • 用LinkedHashset集合(有序,不重复,无索引),底层基于哈希表和双链表
  • 5.如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
    • 用Treeset集合,基于红黑树实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1597089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue实现的医院在线挂号系统(代码+万字文档)

系统介绍 基于SpringBootVue实现的医院在线挂号系统设计了三种角色&#xff0c;分别是管理员、医生、用户&#xff0c;每种角色对应不同的菜单 系统实现了个人信息管理、基础数据管理、论坛管理、用户管理、单页数据管理、医生管理及轮播图管理等功能模块&#xff0c;具体功能…

16.读取指定路径下的txt文档然后合并内容为一个txt文档。

1.题目要求 分别读取路径为 ./middle/phone/base/1_student_0.txt, ./middle/vr/base/1_teacher.txt, ./nearby/phone/base/1_student_0.txt, ./nearby/vr/base/1_teacher.txt, ./outside/phone/base/1_student_0.txt, ./outside/vr/base/1_teacher.txt 里面的文件&#xff…

【LeetCode: 3117. 划分数组得到最小的值之和 + 动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

linux shell脚本编写(2)

Shell: 命令转换器&#xff0c;高级语言转换成二进制语言。是Linux的一个外壳&#xff0c;它包在Lniux内核的外面&#xff0c;用户和内核之间的交互提供了一个接口。 内置命令&#xff1a;在shell内部不需要shell编辑 外置命令&#xff1a;高级语言要用shell转换成二进制语言 …

Numpy数组和列表list的区别

参考&#xff1a;Numpy Array vs List 在Python编程中&#xff0c;列表&#xff08;list&#xff09;和Numpy数组&#xff08;numpy array&#xff09;是两种常见的数据结构&#xff0c;它们都可以用来存储多个元素。但是它们在实际使用中有很大的区别&#xff0c;本文将详细比…

【尚硅谷】Git与GitLab的企业实战 学习笔记

目录 第1章 Git概述 1. 何为版本控制 2. 为什么需要版本控制 3. 版本控制工具 4. Git简史 5. Git工作机制 6. Git和代码托管中心 第2章 Git安装 第3章 Git常用命令 1. 设置用户签名 1.1 基本语法 1.2 案例实操 2. 初始化本地库 2.1 基本语法 2.2 案例实操 3. 查…

RabbbitMQ基本使用及其五种工作模型

初识MQ 同步通讯和异步通讯 什么是同步通讯呢&#xff1f;举个例子&#xff0c;你认识了一个小姐姐&#xff0c;聊的很火热&#xff0c;于是你们慢慢开始打电话&#xff0c;视频聊天&#xff0c;这种方式就成为同步通讯&#xff0c;那什么是一部通讯呢&#xff0c;同样的&…

P1706 全排列问题

原题链接:全排列问题 - 洛谷 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 dfs典题 3. 代码实现 #define _CRT_SECURE_NO_WARNINGS 1 #include<bits/stdc.h> using namespace std; #define ll long long #define endl \n const int N 2…

电脑技巧:Bandicam班迪录屏介绍

目录 一、 软件简介 二、软件功能 2.1 屏幕录制 2.2 游戏录制 2.3 设备录制 2.4实时编辑与截图 2.5 轻量级软件 三、软件用途 3.1 教育培训 3.2 游戏直播与分享 3.3 企业办公 3.4 在线教学与知识分享 四、总结 今天给大家推荐一款非常实用的电脑录屏软件&#xf…

Java实现单点登录(SSO)详解:从理论到实践

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

提高大型语言模型 (LLM) 性能的四种数据清理技术

原文地址&#xff1a;four-data-cleaning-techniques-to-improve-large-language-model-llm-performance 2024 年 4 月 2 日 检索增强生成&#xff08;RAG&#xff09;过程因其增强对大语言模型&#xff08;LLM&#xff09;的理解、为它们提供上下文并帮助防止幻觉的潜力而受…

java-字符串

一、String概述 java.lang.String类代表字符串&#xff0c;java中所有字符串文字都是该类的对象 字符串的内容是不会发生变化的&#xff0c;它的对象在创建之后就不能被更改 二、创建String对象 1、直接赋值 语法&#xff1a; String 变量名内容&#xff1b; 2、使用构造…

Linux 磁盘存储挂载

fdisk -l 查看磁盘信息 mkfs.xfs /dev/vdc 格式化数据盘 mkdir vdev1 创建挂载点 mount /dev/vdc /vdev1 文件系统挂载点挂载 df -h 确认挂载成功 vi /etc/fstab 插入 /dev/vdc /vdev1 xfs defaults 0 0 /dev/vdc /vdev1 xfs defaults 0 0 保存就可以了 卸载实例&#…

韩顺平 | 零基础快速学Python(16) 文件处理

文件 输入与输出 输入&#xff1a;数据从数据源(文件)到程序(内存)&#xff1b; 输出&#xff1a;数据从程序(内存)到数据源(文件)。 #mermaid-svg-06PG6JZq4jJMV1oH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

SpringBoot源码解析-01

SpringBoot3详细版 一&#xff1a;SpringBoot引入&#xff1a; 1.1.什么是Springboot&#xff1a; SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用&#xff08;说明&#xff1a;SpringBoot底层是Spring&#xff09; 大多数 SpringBoot 应用只需要编…

洛谷 P9532 [YsOI2023] 前缀和

题目背景 Ysuperman 模板测试的试机题。 小心立秋&#xff0c;小心秋丽。 题目描述 立秋有一个长度为 n 的数组 a&#xff0c;所有数字都是正整数&#xff0c;并且除了其中第一个数字以外其它数字都等于前面所有数字的和。 例如&#xff0c;数组 [1,1,2,4,8,16] 就有可能是…

如何入行产品经理?

转产品经理第一点要先学基础理论知识&#xff0c;学了理论再去实践&#xff0c;转行&#xff0c;跳槽&#xff01; 学理论比较好的就是去报NPDP的系统班&#xff0c;考后也会有面试指导课&#xff0c;跟职场晋升课程&#xff0c;对小白来说非常合适了~&#xff08;可以去哔站找…

【程序分享】AACSD 程序: 用于晶体结构和缺陷的原子分析平台

分享一个 AACSD 程序: 用于晶体结构和缺陷的原子分析平台。 感谢论文的原作者&#xff01; 主要内容 “我们开发了一个名为 AACSD&#xff08;晶体结构和缺陷原子分析器&#xff09;的高效命令行程序&#xff0c;用于对各种原子模拟代码生成的原子配置进行后期分析。该程序不…

利用栈删除数组中重复元素

先将数据排序&#xff08;降序或升序&#xff09; 建立一个“栈”&#xff0c;三种情况&#xff1a; 1.栈为空&#xff1a;压入一个元素 2.栈不为空 且 栈顶元素不等于将入栈元素&#xff1a;压入一个元素 3.栈不为空 且 栈顶元素等于将入栈元素&#xff1a;删除将压入元素…

循环双链表的操作

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 每一个裂缝都是为透出光而努力&#…