Java SE学习总结 Day (19)

Day 19开篇:
      
        "
今天java基础主要学习了Set的定义,Set的特点,HashSet,HashSet的特点,HashSet注意项,LinkedHashSet,TreeSet等。" 




知识点反馈:

今天的知识点和每周总结的思维导图

 


 



 

一.Set
1. 定义:
是一个无序,元素不可以重复
 
2. Set的特点:
(1) 他是Collection,他并没有提供额外的方法,所以我不说他的方法了
(2) Set不允许出现重复元素
(3) Set我一般都说是无序的(误认为他是随机),但是并不是.我们以HashSet来举例
 
3. HashSet:
(1)定义:
HashSet是Set接口的典型实现,大部分时候,我们说Set用的都是HashSet
(2)HashSet的特点:
a.不能保证元素的迭代顺序
b.此类允许使用 null 元素
c.不是线程安全的
 
4.为什么说HashSet是无序的:
因为HashSet是元素不重复:
假如我们自己写一个元素不重复的代码,你这么处理?
我们肯定使用equals()方法
 
5.HashSet本质上还是依靠数组进行维护的
 
6.HashSet数据添加的时候会进行如下处理:
(1)先获取数据的HashCode的值
(2)通过过一个哈希算法,算出HashCode的具体值(这个值其实也就是索引位置)
(3)将数据插入到指定索引位置
情况1:
这个索引位置不存在任何元素,直接插入(其实哈希码表在严格意义上来说,已经对每一个类型都进行了哈希的分类,如果这个索引不存在元素,则说明该类型从未进入到数组,则肯定不出现重复。)
情况2:
这个索引位置已经存在元素(算出来的哈希值是一样的)。
     情况1:哈希值一样,但是可能内容不一样这个情况会先调用equals方法进行对比,不相同则开拓链表在同一位置进行插入
     情况2:哈希值一样,但是可能内容也一样新的的内容不允许添加(equals为true则不满足,无法添加,equals为false则满足,直接添加)
 
7. 例子:
public class Demo {
    public static void main(String[] args) {
        //Set set = new Set();//接口不允许实例化
 
        //HashSet,提到Set,我们的第一印象可能不能重复,元素无序(插入和取出顺序不一致)
        //元素无序(插入和取出顺序不一致),说法请推翻
        //理论上开说,貌似是这样
        //实际上并不是
        Set set = new HashSet();
        set.add("toobug");
        set.add("王健林");
        set.add("马化腾");
        set.add("王思聪");
        set.add("马云");
        set.add("马云");
 
        Iterator it = set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}
 
8.案例:
        我们创建了一个对象,然后对象分别添加到Set集合当中 但是,Set并没有给我们去重写的原因?
(1)因为每一个对象的hashCode都是不同的,而现在默认比较是地址值是否相同
     解决方法:
                    重写了子类的equals方法,但是却并没有被调用
     原因:因为现在每一个对象的hashCode地址不同,所以直接就插入,根本不需要equals进行判断
(2)如何使才能equals调用起来?
      equals调用的前提是对象的hashCode相等,算出来索引位置相等,才会进行二次对比(调用equals)
(3)如何才能让对象具备相同的散列码(哈希地址),写这个东西你得先了解他的哈希算法是怎么算的。
      可以直接使用IDEA进行生成重写hashCode方法,默认使用的是Arrays的hashCode()
(4)hashCode()
                       result = 31 * result + (element == null ? 0 : element.hashCode());
                       31占用的是5bits, 如果相乘造成的数据溢出的概率会比较的小,现在很多虚拟机基本都有进行优化,原则你的散列系数越大效率也就越高,也就越安全。
                       31是不是一个素数,素数的作用就是如果我用每一个数字来乘以这个素数,那么最终的结果只能被素数本身和1来进行整除(一定程度上减少冲突)
 
9. HashSet注意事项:
(1)HashSet并不是随机性的,而是通过哈希码计算的值跟我们理想插入顺序不一致而已,取出还是顺序进行取出的
(2)重写equals,在HashSet并不会进行调用,此时应该保证相同对象必须具备相等散列码 所以斤应该重写对象的HashCode,致使equals能够被调用起来。通常来说,参与计算equals的值应该同步放到HashCode进行同步计算。
 
10.LinkedHashSet:
(1)LinkedHashSet其实就是HashSet的子类,本质上也是通过计算hashCode来决定元素的存储位置(跟HashSet处理的方式也一致)。
(2)那LinkedHashSet是怎么保证插入和取出顺序是一致?
其实就是LinkedHashSet又多提供了一个双向链表进行维护次序,所以就使得元素看起来是迭代顺序有序的。 从性能来说LinkedHashSet插入的性能略低于HashSet。
 
11.HashSet:
底层维护的是数组,初始化容量16,如果容量的使用率超过0.75(16*0.75=12),就会自动扩增原来容量的2倍(16*2=32)
 
12. TreeSet:
(1)作用:
TreeSet可以确保我们集合的元素处于一个排序状态。其实他排序的底层实现的是二叉树结构(红黑树)来进行数据的存储。
(2)TreeSet提供排序方式:
<1>自然排序
    a.只要你的数据具备自然排序的规则,就可以默认的使用Comparable进行排序
   如果说,元素不具备排序规则,那么就会造成类型转换失败(排序的前提一定是同一个类型,且具备排序规则)
    b.如果是对一个对象的某个字段进行排序,则需执行两个步骤:
                1.实现Comparable接口
                2.重写compareTo方法
    c.如何重写?
                this.成员变量 - o.成员变量(转型的问题)
 
 
    d.Comparable:
                此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
    c. ClassCastException:类型转换失败异常
 
             
<2>定制排序:
        a.自己定义个排序类
        b.该类实现Comparator这个接口
        c.重写该类的compare的方法,制定排序规则
        d.创建TreeSet类,并且将自定义的排序类创建对象,传到TreeSet对象构造当中
         MyComparable mc = new MyComparable();
         TreeSet ts = new TreeSet(mc)


 

发布了29 篇原创文章 · 获赞 7 · 访问量 3163

猜你喜欢

转载自blog.csdn.net/weixin_45406656/article/details/104271525