2021年1月31日 单列集合

为什么List集合存取顺序是一样的?

List是顺序存储的,即元素的存储结构是有顺序性的,第一个存入的元素会第一个被遍历到。

 

ArrayList与LinkedList的相同之处就是在于:

他们之中的元素都是按照存入顺序存储的

ArrayList是连续存储的,所以查找快,增删慢

LinkedList是不连续存储的。所以查找慢,增删快

 

对比ArrayList与LinkedList的查找速度:

 

 

 上面说的查找快慢不是绝对的,由于LinkedList可以从尾端开始找,有时候会比ArrayList快

为什么Set集合存取顺序不一样?

因为不管是HashSet还是TreeSet,都有自己独特的存储结构,存入时的规则、遍历的顺序与存储结构有关,与存入的先后顺序无关。

比如元素是学生,Set是校园

张三7点到校,去4班上课

李四7点半到校,去3班上课

王五8点到校,去1班上课

级部主任按照班级序号进行点名,

那么这三位学生被点到的次序就是:王五,李四,张三

但是早上上学他们到的先后顺序是:张三、李四、王五

为什么Set集合不能有重复元素?

Set的实现类

TreeSet集合,内部存储结构是二叉树

HashSet集合,内部存储元素的结构是哈希表

 

HashSet依靠hashCode()和equals()方法约束内部元素的唯一性。

HashSet的基本结构是:数组(存放hashcode)+链表(或二叉树),每个数组指向一个链表

而从Object类中继承过来的hashCode()和equals()方法是这样的:

发现没有方法体, native表示该方法是外部定义的,C语言写的

但是我们能确定他肯定和内存地址有关

equals比较的就是内存地址。

所以如果想用HashSet集合存储自定义类型的元素,就需要重写该类的hashcode和equals方法,规定值相同的元素是重复的

比如下例中定义了一个Circle类,并规定只要半径相同就是重复的圆,如果我们不重写equals或hashcode中任意一个方法,都会输出四个圆

 

class Circle{
    double radius;
    Circle(double radius){
        this.radius = radius;
    }
    public String toString() {
        return "A Circle : "+radius;
    }

    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;
        temp = Double.doubleToLongBits(radius);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Circle other = (Circle) obj;
        if (Double.doubleToLongBits(radius) != Double.doubleToLongBits(other.radius))
            return false;
        return true;
    }
    
}


public class Main {
    public static void main(String[] args){
        HashSet<Circle> hs = new HashSet<>();
        
        hs.add(new Circle(5.5));
        hs.add(new Circle(5.5));
        hs.add(new Circle(5.5));
        hs.add(new Circle(5.5));
        
        System.out.println(hs);
        
        for(Circle c:hs) {
            System.out.println(c.hashCode());
        }

    }
}

LinkedHashSet与HashSet

查看源码发现:LinkedHashSet是HashSet的子类

 

 

LinkedHashSet在内部存储时,在哈希表的基础上,每个元素还保存了前一个和后一个元素的内存地址,以达到存入顺序与遍历顺序一致:

 

 

 对比LinkedHashSet与HashSet的区别(还是使用上面的圆类):

可见LinkedHashSet即能保证元素不重复,又可以按照存入顺序遍历出来。

posted @ 2021-01-31 15:33  lucascube  阅读(97)  评论(0)    收藏  举报