zoukankan      html  css  js  c++  java
  • [Java核心技术]第九章-集合(Java集合框架、具体的集合、映射)

    9.1Java集合框架

    一些有的没的

    • 可以使用接口类型存放集合的引用。一旦改变了想法,只需要在调用构造函数的地方做一处修改。
    • add方法用于向集合添加元素,如果添加元素确实改变了集合就返回true。
    • tostring()方法用来调试。

    迭代器

    • 不同于C++,查找操作与迭代器的位置变更是紧密相连的,在执行查找操作的同时,迭代器的位置随之向前移动。
    • Iterator接口的remove方法:删除上次访问的对象(即调用next方法时返回的元素)。

    Queue、Deque extends Queue接口。(队列)

    队列实现的两种方式的选择:

    • 循环数组 ArrayDeque。优先选择,更高效。
    • 链表 LinkedList。程序中要收集的对象数量没有上限时选择。

    List接口

    • List是一个有序集合
    • 两种实现方式:数组、链表
    • 测试一个集合是否支持高效的随机访问if(c instanceof RandomAccess)

    Set、SortedSet extends Set、NavigableSet extends SortedSet接口

    • 基本等同于Collection接口,区别在于不允许重复。
    • Set中的元素必须实现了equals和hashCode方法。
    • SortedSet接口,提供用于排序的比较器对象,可以得到集合子集视图?
    • NavigableSet接口,包含一些搜索和遍历有序集的方法。

    9.2具体的集合

    Part1 链表

    LinkedList类(链表)

    • 从数组中间删除元素代价很大
    • Java中,所有的链表底层都是双向链表
    ListIterator接口
    • 链表和泛型集合重要区别,链表是一个有序集合。区别Collection.add和ListIterator.add。后者不返回boolean类型值,假定操作总会改变链表。后者在迭代器位置前插入listiter.next();listiter.add("hello");,前者在链表尾部插入。
    • ListIteraror接口有两个方法,previous和hasPrevious(),用来反向遍历链表。
    • 可以给容器附加很多个迭代器,但只能有一个可写可读的迭代器。如果一个迭代器发现它的集合被另一个迭代器/集合自身方法 修改了,就会抛异常。
    • 检测并法修改问题的方法:每个迭代器维护一个独立的计数值,若发现与集合改写操作计数值不一致,则抛异常。
    • 程序需要随机访问时,通常不选择链表。同时,尽量避免引用索引访问链表。

    ArrayList类(数组列表)

    Part2 集合

    HashSet类(散列集)

    • 放入其中的元素必须实现hashCode方法和equals方法。且两者兼容,即a.equals(b)==true则a与b必须具有相同的散列码。
    • Java中,散列表用链表数组实现。每个列表称为桶。查找表中对象:计算它的散列码,然后与桶的总数取余,所得到的结果就是保存这个元素的桶的索引。散列表只在某个桶中查找元素,而不必查看集合中的所有元素。
    • ASL,指查找算法的查找成功时的平均查找长度,是为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值。
    • 散列冲突:指不同对象散列到相同的hashcode。解决方法如下,
      • 开发定址法:例如线性探测再散列,即产生冲突后 原查找对象+1 再做hash ,若产生冲突,原查找对象+2 再做hash,直到找到空的地方。
      • 再哈希法:即产生冲突后用第二种hash函数。
      • 链地址法:Java中HashSet采用这种方法。
      • 建立一个公共溢出区:冲突的都放在公共溢出区。
    • 桶满时,会发生散列冲突。Java 中,桶满时会从链表变为平衡二叉树。
    • 设置桶数:如果大致知道要有多少个元素插入散列表,就可以设置桶数。通常设置为预计元素的75%-150%。标准类库使用的桶数是2的幂,默认值16。
    • 装填因子决定何时对散列表进行再散列(创建一个桶数更多的表,将所有元素插入新表,丢弃原来的表):默认值0.75,超过75%的位置已经填入元素后,会用双倍的桶数进行再散列。
    • JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
    • HashSet如何检查重复:当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加入操作成功。
    • ==与equals的区别
      ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同
      ==是指对内存地址进行比较 equals()是对字符串的内容进行比较
      ==指引用是否相同 equals()指的是值是否相同
    • HashMap的数组长度为什么是必须是2的幂次
      散列值用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。但源码中这个数组下标的计算方法是“ (n - 1) & hash”。(n代表数组长度)。
      因为当length是2的幂,有 hash%length==hash&(length-1)。
      且&操作相对于%能够提高运算效率。

    TreeSet类

    • TreeSet是有序集合,对集合进行遍历时,每个值自动地安排序后的顺序呈现。底层使用红黑树实现。元素必须实现Comparable接口,或调构造函数时传入comparator对象。
    • 性能:TreeSet添加元素比添加到HashSet慢。
    • TreeSet与HashSet的选择:如果需要排序,再使用TreeSet,因为有额外开销。

    SortedSet extends Set ,接口

    扩展了SortedSet,具有了搜索匹配元素的方法。

    Part3 队列

    ArrayDeque implements Deque ,类;LinkedList implements Deque ,类

    • 以上两个类实现了双端队列,并都可无限长度。ArrayDeque默认初始容量16。
    • java.util.Queue 方法
      • 入队 add/offer 抛异常/返回false
      • 出队 remove/poll 抛异常/返回null
      • 获得队首元素 element/peek 抛异常/返回null
    • java.util.deque 方法
      • addFrist/addLast
      • 其他形式同上

    PriorityQueue类

    • 优先队列,底层实现堆。。堆是一个可以自我调整的二叉树,对堆执行add和remove操作,可以让最小的元素移动到根,而不必花费时间对元素进行排序。
    • 优先级队列中元素必须实现Comparable接口,或构造器中提供实现了Comparator接口的对象。
    • 使用优先级队列的典型示例是任务调度。

    Part* 哈希表、红黑树、堆时间复杂度

    哈希表:查找、插入、删除均为O(1)
    堆:得到最大值最小值O(1)、插入删除O(logn)
    红黑树:查找、插入、删除均为O(logn)

    9.3 映射

    基本操作

    • get、put、containsKey

    遍历map

    scores.foreach(
        (k, v)->{
           //do something with k,v
        }
    );
    

    更新value???

    counts.merge(word,1,Integer::sum);
    

    完成+1操作。word原来不存在也可以处理,不会出错。

    映射的视图:是实现了Collection接口或某个子接口的对象。

    Set<K> keySet()   //key集合
    Collection<V> values() //value集合
    Set<Map.Entry<K,V>> entrySet()  //key value 集合
    

    Set<String> keys=map.keySet();
    
  • 相关阅读:
    页面性能:如何系统地优化页面?
    为什么CSS动画比JavaScript高效?
    Code Review
    浏览器中的页面之CSS是如何影响到渲染流程的
    async / await
    手撸Promise
    Promise
    宏任务和微任务
    有点恶心,随手写点儿
    关于判断用户输入的是不是int类型,这次没有正则表达式
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/11035738.html
Copyright © 2011-2022 走看看