Javase基础笔记 【集合Collection、Map】

Collection接口方法

在这里插入图片描述

* 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals().
//1.contains(Object obj):判断当前集合中是否包含obj
//在判断时会调用obj对象所在类的equals()。
 coll.add(123);
 System.out.println(coll.contains(new Person("Jerry",20)));//false -->true
@Override
    public boolean equals(Object o) {
        System.out.println("Person equals()....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }
 //把123放入new对象所在类的equals方法形参

Iterator迭代器接口

内部方法:hasnext()和next()
调用后者前要用前者检测下一条记录是否有效,否则直接调用next()会抛出NoSuchElementException异常

  • 使用Iterator遍历collection
while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

错误方式一:
nosuchelementexception空指针、间隔输出

      Iterator iterator = coll.iterator();
      while(iterator.next() != null){
          System.out.println(iterator.next());
      }

错误方式二:
死循环,每次实例化后都会生成一个指向容器顶部的iterator指针

while(coll.iterator().hasNext()){
    System.out.println(coll.iterator().next());
}

Collection子接口:List

List接口的实现类常用的有:ArrayList、LinkedList和Vector

  • |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储

  • |----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储

  • |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储

jdk 8中ArrayLis底层 :变长数组
Object[] elementData初始化为{},第一次调用add时才创建了一个长度为10的数组。扩容方面:默认扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中

LinkedList底层:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。

vector底层:大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。扩容方面:默认扩容为原来数组的两倍。

增强for循环在这里插入图片描述
List接口常用方法
在这里插入图片描述

Collection子接口:Set接口

  • |----Set接口:存储无序的、不可重复的数据 -->“集合”
  • |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
  • |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历。对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
  • |----TreeSet:可以按照添加对象的指定属性,进行排序。

向hashset中添加元素的过程在这里插入图片描述

添加过程注释

  • 若此位置已有其他元素(或以链表形式存在多个),则比较元素的hash值:存在hash值不同但通过某种算法被分为同一索引位置的可能。(注:如果使用率超过0.75,底层数组会扩容为原来的二倍)。
  • 如果hash值相同,需要调用元素a所在类的equals()方法: 存在由于hashcode计算方法设计出现的偶然情况(两个截然不同的实例有可能在逻辑上是相等的),如
    a.name=jack (1) a.age=13(2) hashcode 1+2=3
    b.name=ann(2) b.age=32(1) hashcode 2+1=3
    通过equals来判断name和age是否相等
    ~
    所以重写的hashCode()和equals()需要尽可能保持一致性:
    相等的对象必须具有相等的散列码。

HashSet 集合判断两个元素相等的标准
两个对象通过hashCode() 方法比较相等,并且两个对象的equals()方法返回值也相等。

LinkedHashSet:
是hashset的子类,插入性能略低于hashset,频繁遍历操作效率更高,使用双向链表维护元素次序。

Map的实现类结构

|----Map:双列数据,存储key-value对的数据 —类似于高中的函数:y = f(x)
||----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
|||----LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,此类执行效率高于HashMap。
||----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树
||----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
|||----Properties:常用来处理配置文件。key和value都是String类型
HashMap的底层
数组+链表 (jdk7及之前)
数组+链表+红黑树 (jdk 8)

Map结构的理解

  • Map中的key:无序的、不可重复的,使用Set存储所有的key —> key所在的类要重写equals()和hashCode() (以HashMap为例)
  • Map中的value:无序的、可重复的,使用Collection存储所有的value —>value所在的类要重写equals()
  • 一个键值对:key-value构成了一个Entry对象。
  • Map中的entry:无序的、不可重复的,使用Set存储所有的entry

HashMap底层实现原理

DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
threshold:扩容的临界值,=容量*填充因子:16 * 0.75 => 12
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64

JDK7:数组+链表
实例化HashMap时,会创建一个长度(哈希表初始容量)为Capacity的Entry数组,存放元素的位置称为桶(具有索引)。Entry对象带一个引用变量,用于指向下一个元素形成Entry链,元素插入(7上头插),添加过程同hashset。
扩容:当超出临界值(且要存放的位置非空)时。
默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。是一个非常消耗性能的操作。

JDK8:数组+链表+红黑树
实例化HashMap时,会创建一个长度为InitialCapacity的Node数组,存放元素的位置称为桶(具有索引)。Node对象带一个引用变量,可能会形成Node链或变为TreeNode对象生成TreeNode树。
扩容同上
Treeify树形化:当HashMap中的其中一个链的对象个数如果达到了8个,此时如果capacity没有达到64,那么HashMap会先扩容解决,如果已经达到了64,那么这个链会变成红黑树,结点类型由Node变成TreeNode类型。

总结:
jdk8 相较于jdk7在底层实现方面的不同

  1. new HashMap():底层没有创建一个长度为16的数组
  2. jdk 8底层的数组是:Node[],而非Entry[]
  3. 首次调用put()方法时,底层创建长度为16的数组
  4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
    形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
    当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。

**LinkedHashMap的底层实现原理**
是HashMap的子类,与LinkedHashSet类似。
LinkedHashMap可以维护Map 的迭代顺序:迭代顺序与Key-Value 对的插入顺序一致

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

HashMap的底层实现原理?
HashMap 和 Hashtable的异同?
1.HashMap与Hashtable都实现了Map接口。由于HashMap的非线程安全性,效率上可能高于Hashtable。Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。
2.HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
3.HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
4.Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

Collections工具类

Collections 是一个操作Set、List和Map 等集合的工具类

Collection 和 Collections的区别?
Collection是集合类的上级接口,继承于他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作.

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值