集合-备忘录

跳转到总目录


集合-备忘录

Java 集合可分为Collection和Map两种体系.

  • Collection接口:单列集合,用来储存一个一个的对象.
    • List:存储有序的、可重复的集合.
      • ArrayList,LinkedList,Vector
    • Set:存储无序的、不可重复的集合.
      • HashSet,LinkedHashSet,TreeSet
  • Map接口:双列集合,用来存储键值对(key-value)数据.
    • ---- HashMap,LinkedHashMap,TreeMap,HashTable

Collection集合

常用方法:

size(): 有效数据个数.
add(E e): add自定义类时要重写equals(contains()和remove()等要用到equals).
addAll(Collection coll): 添加整个集合coll.
contains(Object obj): 是否包含obj.
containsAll(Collection coll): 是否包含整个集合coll.
remove(Object obj): 移除obj.
removeAll(Collection coll):移除整个集合coll.
retainsAll(Collection coll): 交集和removeAll一样直接修改原集合.
iterator(): 返回迭代器对象,用于集合遍历,里面有hasNext(),next(),remove()方法.
equals(Object obj): 是否相同.
hashCode():获取哈希值.
toArray(): 转成对象数组,拓展Arrays.asLlist()转成集合.
clear(): 清空.
isEmpty(): 是否为空.


List集合

  • ArrayList: 作为List接口的主要实现类,线程不安全的,效率高,底层使用Object[]存储.
  • LinkedList: 底层使用双向链表,对于频繁的插入,删除操作,使用此类效率比ArrayList高.
  • Vector: 作为List接口的老实现类,线程安全的,效率低,底层使用Object[]存储.

ArrayList底层代码:

空参初始化时默认Object[]大小为{}的空集合,再add()时创建大小为10,默认扩容为1.5倍,同时将原有数组复制到新数组中(建议数据量大时,使用带参的构造器指定初始大小).

LinkedList底层代码:

空餐初始化时默认为null,内部声明了Node类型的first和last属性,该Node定义体现了双向链表.

Vector底层代码:

默认长度为10,默认扩容为原来的2倍.

常用方法:
除Collection中写过的以外的List的常用方法:

add(int index, Object obj): 在index位置插入元素.
addAll(int index, Collection coll)
get(int index): 获取指定index位置的元素.
indexOf(Object obj): 返回obj在集合中首次出现位置,没有则为-1.
lastIndexOf(Object obj): 末次出现的位置.
remove(int index): 移除指定index位置的元素,并返回该元素.
set(int index, Object ele): 设置index处元素为ele.
subList(int from, int toIndex): 返回from到toIndex的集合(左开右闭).


Set集合

  • HashSet: 作为Set接口的主要实现类,线程不安全的,可以存储null值.
    ----- LinkedHashSet: 作为HashSet的子类,遍历时可以按添加顺序输出(还是无序).
  • TreeSet: 可以按照添加对象的指定属性排序.

注意: Set接口中没有额外定义新的方法,使用的是Collection中声明的.

向Set中添加的数据所在类一定要重写hashCode()和equals(),重写时要尽量保持一致性: 相等的对象必须具有相同的散列码.推荐使用自动生成的,自己写的话,对象中的用作equals()方法比较的Field都应该计算hashCode().
HashSet为例说明:

无序性: 不等于随机性,添加时根据哈希值加的,不按数组索引顺序.
不可重复性: 相同的元素又添加一个,是先根据hash值算出下标,然后通过hash值判断,再通过equals判断,所以hashCode()和equals()这两种方法要重写.

LinkedHashSet为例说明:

其在添加数据的同时,每个数据还维护了两个引用(双方链表)来记录前后数据.
优点:
对于频繁的遍历操作,LinkedHashSet效率高于HashSet.


添加元素过程, 以HashSet为例:

HashSet底层用的是HashMap,所以底层是数组+链表(或红黑树).
添加元素a,首先调用a的hashCode(),计算a的哈希值,接着通过高位运算+取模运算算出正真的hash值,最后通过某种算法得出底层数组中的索引位置,判断此位置上是否有元素.

  • 没有则元素a添加成功. --> 情况1
  • 有其他元素(多个元素)则比较与其他元素的hash值:
    ---- hash值不相同则元素a添加成功. --> 情况2
    ---- hash值相同则调用元素a的equals()方法:
    • ---- equals()返回true,元素a添加失败
    • ---- equals()返回false,元素a添加成功. --> 情况3

对于情况2,3来说,a元素在指定索引上以链表方式存储:
JDK7: 元素a放到数组中,指向原来的元素.
JDK8: 原来的元素在数组中, 指向元素a.
总结七上八下.

TreeSet类

必须添加相同类型数据,因为会排序.
两种排序方式: 自然排序(Comparable)和定制排序(Comparator).
TreeSet中比较两个对象是否相同标准为其实现的排序方式中重写的方法返回为0,而不是equals().


Map集合

  • Map: 双列数据,储存key-value对数据.
    ---- HashMap: 作为Map的主要实现类;线程不安全的,效率高,可以存null值得key和value.
    • ---- LinkedHashMap: 可以按照添加的顺序实现遍历,因为在原先HashMap的基础上添加了一对指向前后元素的指针.
  • ---- TreeMap: 按照key进行排序,实习排序遍历.底层使用红黑树.
  • ---- Hashtable: 作为古老的实现类,线程安全的,效率低,不能存null的key和value.
    • ---- Properties: 常用来处理配置文件,key和value都是String.

Map结构理解(以HashMap为例):

Map中的key: 无序的,不可重复的,使用Set存储所有的key,key所在类需要重写hashCode()和equals.
Map中的value: 无序的,可重复的,使用Collection存储所有的value,value所在类要重写equals.
一个键值对构成一个Entry对象.
Map中的Entry: 无序的,不可重复的,使用Set存储所有的entry.

HashMap底层实现原理(以JDK7为例):

HashMap map = new HashMap();
在实例化后,底层创建长度是16的一维数组Entry[] table.
map.put(key1 , value1):
首先调用key1所在类的hashCode()然后将哈希值进行高位运算+取模运算,最后通过某种运算得出在Entry数组中的
索引位置,判断此位置上是否有数据.
- 如果此位置上数据为空,此时的key1-value1添加成功. --> 情况1
- 若不为空.意味此位置上有一个或多个数据(链表形式存在),比较key1和已存在的所有数据的hash值:
 ---- 如果key1和已存在的所有数据hash值都不相同,则key1-value1添加成功. --> 情况2
 ---- 如果有存在相同hash值的key2-value2,则继续比较:
     - ---- 如果equals()返回false,添加成功. --> 情况3
     - ---- 返回true,使用value1替换value2.
 
对于情况2,3来说,以链表方式存储.
默认扩容为原来的2,负载因子为0.75f,l临界值为长度*负载因子,超出临界值,且存放的位置非空,并将原先数据
复制.
jdk8改动点:
1. 实例化时底层没有直接创建长度为16的数组,首次put()时才创建.
2. 底层数组名由Entry改为Node,内部结构继承Entry.
3. jdk7底层只有数组+链表,jdk8底层为数组+链表+红黑树,当数组某个索引位置上的元素以链表形式存在的数据
个数大于8且当前数组长度大于64,此索引位置上的数据改为用红黑树.

注意点:
LinkedHashMap的put()方法直接调用了父类(父类就是HashMap)的,但它重写了newNode(…),并新建了Node类的子类,多了前后节点的指针(引用),用来记录添加元素的先后顺序.

Map的常用方法:

Object put(Object key, Object value): 将指定key-value添加或修改.
void putAll(Map m): 将m中所有key-value存在到当前map中.
Objecct remove(Object key): 移除指定key的key-value,并返回value的值.
void clear(): 清空所有数据.
Object get(Object key): 获取指定key对应的value.
boolean containsKey(Object key): 是否包含指定的key.
boolean containsValue(Object value): 是否包含指定的value.
int size(): 返回key-value对个数.
boolean isEmpty(): 是否为空.
boolean equals(Object obj): 判断当前map和参数对象obj是否相同.
Set keySet(): 返回所有key构成的Set集合.
Collection values(): 返回所有value构成的Collection集合.
Set entrySet(): 返回所有key-value构成的集合.

TreeMap类

添加的数据key必须是同一对象,因为需要对key进行排序(自然排序: Comparable 定制排序: Comparator).


Properties类

Properties是Hashtable的子类,常用来处理配置文件,key和value都是String格式的.
常用方法:

load(文件流): 加载流对应文件.
getProperty(String key): 获取.


Collections类

Collections是工具类,操作Collection和Map的.
常用方法:

reverse(List list): 反转元素 .
shuffle(List list): 随机排序.
sort(List list): 自然排序.
sort(List list, Comparator comp): 定制排序.
swap(List list, int i, int j): 将两元素交换.
max(Collection coll): 自然排序下的最大元素.
max(Collection coll, Comparator comp): 定制排序下的最大元素.
min和max用法相同.
frequency(Collection coll, Object obj): 指定元素出现的次数.
copy(List dest, List src): 将src中的内容复制到dest中,dest.size()要大于等于src.size().
replaceAll(List list, T oldVal , T newVal): 用新值替换所有旧值.
synchronizedXxx(Xxx x): 将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值