List与Map

List、Set接口是继承collection父接口的,

List它是按照对象的进入顺序进行保存的,因此,它可以能对列表中的每个元素进行存入和删除的位置,能够精确地控制。list保存的数据是可以重复的,list的子类有LinkedList、Vrctor和ArrayList集合。

总结:List是一种有序(存储顺序)可重复(元素)的集合。

Set接口也是和List一样继承Collection接口。Set在数学上的意义就是集合的概念,他和List不一样的是,不允许集合中的元素重复。所以存入的元素都必须定义equals()方法来确保对象的唯一性,Set接口有两个实现来Hashset和TreeSet,其中TreeSet是实现了SortedSet接口的。

总结:Set是一种无序(存储顺序)不可重复(元素)的集合。

Map集合它提供了一个键映射到值的一个数据结构,记住map的值是个重复,但键是唯一的,Map的子类有很多比如创建的是HashMap和LinkedHashMap。

总结:Map是一种以键值对形式存储的集合。

 

 

List:ArrayList,LinkedList,Vector

1.ArrayList:是线程不安全的,效率高。

2.Vector:是线程安全的。

3.ArrayList和Vector都可以使用for语句或者迭代器遍历,但是Vector还可以使用枚举遍历。

 

LinkedList:采用双向循环链表实现。可以快速执行插入,删除的方法。线程不安全。

ArrayList:采用变长数组算法实现的,特点是:快,线程不安全。

Vector:采用变长数组算法实现的,特点是:慢,线程安全。

 

ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

 

Set区别对象是不是唯一的标准是,两个对象hashcode是不是一样,再判定两个对象是否equals;

Map 是先根据Key值的hashcode分配和获取对象保存数组下标的,然后再根据equals区分唯一值

所以对象需要重写父类(Object)的hashcode方法,Object的hashcode方法会根据两个对象的地址生成对相应的hashcode;

 

hashmap存储

存值规则:把Key的hashCode 与HashMap的容量 取余得出该Key存储在数组所在位置的下标(源码定位Key存储在数组的哪个位置是以hashCode & (HashMap容量-1)算法得出)

 

HashMap的扩容机制

我们向HashMap中存放一个元素(k1,v1),先根据k1的hashCode方法来决定在数组中存放的位置。

如果这个位置没有其它元素,将(k1,v1)直接放入Node类型的数组中,

这个数组初始化容量是16,默认的加载因子是0.75,也就是当元素加到12的时候,底层会进行扩容,扩容为原来的2倍。

 

Java8变成链表和红黑树的组合,数据少量存入的时候优先还是链表,当链表长度大于8,且总数据量大于64的时候,链表就会转化成红黑树,所以你会看到Java8的Hashmap的数据存储是数组+链表+红黑树的组合,如果数据量小于64则只有数组+链表,如果数据量大于64,且某一个数组下标数据量大于8,那么该处即为红黑树。

1.在put()方法中有调用addEntry()方法,这个方法里面是具体的存值,在存值之前还要判断是否需要扩容
    2.调用扩容的方法resize()
    3.扩容必须满足两个条件:
        1、 存放新值的时候当前已有元素的个数必须大于等于阈值
        2、 存放新值的时候当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)
    4.transfer()在实际扩容时候把原来数组中的元素放入新的数组中

Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap

1.HashMap允许存null键和null值,HashTable不允许存null键和null值。

2.HashMap是线程不安全的,HashTable线程是安全的。

3.HashMap可以采用迭代器遍历集合中的元素,而HashTable既可以使用迭代器,还可以使用枚举遍历。

4.哈希表的作用是用来保证键的唯一性;

5.HashMap的实例有两个参数影响其性能:初试容量和加载因子,当哈希表中的条目数超出加载因子与当前容量的乘积时,要对哈希表进行rehash操作(即重建内部数据结构),容量扩大约为之前的两倍,加载因子默认值为0.75;

第一种:遍历HashMap的entrySet键值对集合

1.通过HashMap.entrySet()得到键值对集合;

2.通过迭代器Iterator遍历键值对集合得到key值和value值;

// 获取键值对的迭代器
        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            key = (String) entry.getKey();
            value = (String) entry.getValue();
            System.out.println("key:" + key + "---" + "value:" + value);
        }

 

第二种:遍历HashMap键的Set集合获取值;

1.通过HashMap.keySet()获得键的Set集合;

2.遍历键的Set集合获取值;

 // 获取键集合的迭代器
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            key = (String) it.next();
            value = (String) map.get(key);
            System.out.println("key:" + key + "---" + "value:" + value);
        }

第三种:遍历HashMap“值”的集合;

1.通过HashMap.values()得到“值”的集合

2.遍历“值”的集合;

 // 获取值集合的迭代器
        Iterator it = map.values().iterator();
        while (it.hasNext()) {
            value = (String) it.next();
            System.out.println("value:" + value);
        }

 

Set     HashSet

HashMap相对于HashSet较快,hashset的底层是对HashMap的封装,他们计算value的方式都是一样的,HashSet的底层是HashMap,TreeSet的底层是TreeMap,

场景分析

  1. 如果你经常会使用索引来对容器中的元素进行访问,那么 List 是你的正确的选择。如果你已经知道索引了的话,那么 List 的实现类比如 ArrayList 可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。

  2. 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是 List,因为 List 是一个有序容器,它按照插入顺序进行存储。

  3. 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。

  4. 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值