JDK8单列集合使用

一、单列集合(Collection)

Collection是单列集合的底层接口,它的实现类又分为有序集合(List)和无序集合(Set)

List的经典实现类为:有序,可重复,有索引

(1)ArrayList(基于数组):查询效率高,修改和插入效率低

实现原理:

 1.在使用空参构造创建ArrayList集合时,底层会初始化一个长度为0的数组;

2.在第一次添加数据的时候会创建一个新的长度为10的数组用以实际存储数据;

3.在持续添加过程中,添加的数量超出现有数组的长度,底层会自动创建一个长度为原数组长度1.5倍的新数组,先将原数组数据转存过来,再添加新数据;

 

(2)LinkedList(基于双向链表):查询效率低,修改和插入效率高

实现原理:

 底层基于双向链表实现,在存储的元素中都标记上次元素以及下一个元素的地址

 

Set的经典实现类:无序,不可重复,无索引

HashSet:无序,不可重复,无索引

LinkedSet:有序,无索引,不可重复

TreeSet:排序,不重复,无索引

(1)HashSet

JDK8之前:数组+链表

JDK8开始:数组+链表+红黑树

具体实现特点:

1、创建HashSet对象时底层会先生成一个长度为16,扩容因子为0.75(存满75%自动扩容两倍)的数组

2、当数据需要存储时,底层进行计算,对象的哈希值对数组长度取余,即为存入位置的索引

3、判断索引位是否存在元素,若无,则直接存入数组,若有则需equals比较,相同则不存(不重复原理),不同则挂入

4、JDK8之前,新元素存入数组位置,老元素挂在新元素下,JDK8开始新元素直接挂在老元素下面

5、JDK8之后的特性:若集合中数组长度超过64,链表长度超过8则自动生成红黑树

 

我们发现往HashSet集合中存储元素时,底层调用了元素的两个方法:一个是hashCode方法获取元素的hashCode值(哈希值);另一个是调用了元素的equals方法,用来比较新添加的元素和集合中已有的元素是否相同。

  • 只有新添加元素的hashCode值和集合中以后元素的hashCode值相同、新添加的元素调用equals方法和集合中已有元素比较结果为true, 才认为元素重复。

  • 如果hashCode值相同,equals比较不同,则以链表的形式连接在数组的同一个索引为位置(如上图所示)

在JDK8开始后,为了提高性能,当链表的长度超过8时,就会把链表转换为红黑树,如下图所示:

 (2)LinkedHashSet:

LinkedHashSet是在HashSet的基础上,底层增加了一层链表,让数据可以记录下一个数据的位置,实现顺序存取

 (3)TreeSet

TreeSet集合的特点是可以对元素进行排序,但是必须指定元素的排序规则。

如果往集合中存储String类型的元素,或者Integer类型的元素,它们本身就具备排序规则,所以直接就可以排序。

Set<Integer> set1= new TreeSet<>();
set1.add(8);
set1.add(6);
set1.add(4);
set1.add(3);
set1.add(7);
set1.add(1);
set1.add(5);
set1.add(2);
System.out.println(set1); //[1,2,3,4,5,6,7,8]

Set<Integer> set2= new TreeSet<>();
set2.add("a");
set2.add("c");
set2.add("e");
set2.add("b");
set2.add("d");
set2.add("f");
set2.add("g");
System.out.println(set1); //[a,b,c,d,e,f,g]

如果往TreeSet集合中存储自定义类型的元素,比如说Student类型,则需要我们自己指定排序规则,否则会出现异常。

我们想要告诉TreeSet集合按照指定的规则排序,有两种办法:

第一种:让元素的类实现Comparable接口,重写compareTo方法

第二种:在创建TreeSet集合时,通过构造方法传递Compartor比较器对象

排序方式1:我们先来演示第一种排序方式

//第一步:先让Student类,实现Comparable接口
//注意:Student类的对象是作为TreeSet集合的元素的
public class Student implements Comparable<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;
    }
    //...get、set、toString()方法自己补上..
    
    //第二步:重写compareTo方法
    //按照年龄进行比较,只需要在方法中让this.age和o.age相减就可以。
    /*
    原理:
    在往TreeSet集合中添加元素时,add方法底层会调用compareTo方法,根据该方法的
    结果是正数、负数、还是零,决定元素放在后面、前面还是不存。
    */
    @Override
    public int compareTo(Student o) {
        //this:表示将要添加进去的Student对象
        //o: 表示集合中已有的Student对象
        return this.age-o.age;
    }
}

排序方式2:接下来演示第二种排序方式

//创建TreeSet集合时,传递比较器对象排序
/*
原理:当调用add方法时,底层会先用比较器,根据Comparator的compare方是正数、负数、还是零,决定谁在后,谁在前,谁不存。
*/
//下面代码中是按照学生的年龄升序排序
Set<Student> students = new TreeSet<>(new Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2){
        //需求:按照学生的身高排序
        return Double.compare(o1,o2); 
    }
});

//创建4个Student对象
Student s1 = new Student("至尊宝",20, 169.6);
Student s2 = new Student("紫霞",23, 169.8);
Student s3 = new Student("蜘蛛精",23, 169.6);
Student s4 = new Student("牛魔王",48, 169.6);

//添加Studnet对象到集合
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
System.out.println(students); 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值