中级03 - Collection体系简介

没有 Collection,Java 只能算是玩具。

List
Set
hashCode约定
Map

一、Collection 体系

参考1

参考2

Collection 的体系

  • Collection的体系结构
  • List/Set约定

Collection 体系提供的常⽤⽅法:

  • new: new ArrayList(Collection), new ArrayList()
  • Read: size()/isEmpty()/contains()/for()/stream()
  • Cread/Update: add()/addAll()/retainAll()
  • Delete: clear()/remove()/removeAll()

retainAll()求交集
removeAll()求差集

1. List

有序可重复,最常用的是 ArrayList,本质上就是一个数组

Collection<Integer> c = new LinkedHashSet<>();
        
// IntegerList
List<Integer> list = new ArrayList<>(c);
        
// 等价于
List<Integer> list2 = new ArrayList<>();
list2.addAll(c);
        
// 等价于
List<Integer> list3 = new ArrayList<>();
for (Integer i : c) {
    list3.add(i);
}

add() 方法内部实现了数组的动态扩容:创建一个更大的空间,然后把原先的所有元素拷贝进去。

2. Set

无序且不可重复的元素集合。

只是简单通过object.contains()判断添加新元素时是否重复,从而实现去重的 Set 是很低效的,这就引出了对象的 hashcode。

Java世界⾥第⼆重要的约定:hashCode

  • 同⼀个对象必须始终返回相同的 hashCode
  • 两个对象的 equals 返回 true,必须返回相同的 hashCode
  • 两个对象不等,也可能返回相同的 hashCode

3. 哈希算法

哈希就是⼀个单向、一对多的映射,具有相同 hashCode 的东西存放在同一个 hash 桶中,
例⼦:从姓名到姓到哈希运算
从任意对象到⼀个整数(int)的 hashCode

4. HashSet

HashSet 是无序的,是最常用的 Set 实现。
可以利用 set 为 list 过滤去重:

List<Integer> list = new ArrayList<>();

list.add(2);
list.add(3);
list.add(3);
list.add(3);
        
Set<Integer> set = new HashSet<>(list); 

LinkedHashSet 是有序的,其维护了一个双向(doubly-linked)链表,顺序就是插入元素时的顺序。

5. Collections ⼯具⽅法集合

  • emptySet():返回一个方便的空集合
  • synchronizedCollection:将⼀个集合变成线程安全的
  • unmodifiableCollection:将⼀个集合变成不可变的(也可以
    使⽤ Guava 的 Immutable)
  • unmodifiableSet(): 可以获取不可变的 set,System.getenv() 内部就使用了这个方法将环境变量转换为不可变的 set。

6. Collection的其他实现

  • Queue/Deque
  • Vector/Stack(已废弃,现用 ArrayList/Deque)
  • LinkedList
  • ConcurrentHashMap
  • PriorityQueue

二、Map 体系

map 是 一个将 keys 映射到 values 的对象,键不能重复,每个键只能映射一个值,值可以重复。

Create/Update: put()/putAll()

Read:

  • get()/size()
  • containsKey()/containsValue()
  • keySet()/values()/entrySet()

Delete: remove()/clear()

image.png

keySet()返回键的集合,因为键不可重复,所以可以返回一个 set;
values()返回值的集合,因为值可以重复,所以返回的是 collection。
注意:keySet() 和 map 背后的 keys 是同一组数据,所以二者的修改会相互影响。

entrySet()返回键值对的集合(Set<Map.Entry<K, V>>),遍历时很有用:

Map<String, String> map = new HashMap<>();

for (Map.Entry<String, String> entry: map.entrySet()) {
    System.out.println(entry.getKey());
    System.out.println(entry.getValue());
}

1. HashMap

HashMap 是最常用、最高效的 Map 实现。

HashMap 的扩容,思路同样是创建更大的空间,然后把之前的数据 copy 进来。

HashMap 是多线程不安全的,可使用 ConcurrentHashMap。

HashMap在Java 7+后的改变(链表 --> 红⿊树):
因为 hashCode 是可能重复的(即发生碰撞),极端情况下如果一组数据的 hashCode 全部相同,那么会全放在同一个 hash 桶中成为了一个 List 链表,此时就丧失了 hash 桶的好处,性能会急剧恶化,所以 Java 7 开始会采用红黑树来代替链表。

HashMap 和 HashSet 本质上是同一个东西:
HashMap 的 key 集合(set)就是 HashSet,而 HashSet 内部其实就是个 HashMap,毕竟 HashSet 拥有的功能 HashMap 都有。

2. 有序集合TreeSet/TreeMap

TreeSet 可以排序(默认是自然顺序)。
HashSet、LinkedHashSet 与 TreeSet 对比:

import java.util.*;

public class Main {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1000, -13, 0, -41656, 1250, 555);

        Set set1 = new HashSet<>(list);
        Set set2= new LinkedHashSet(list);
        Set set3 = new TreeSet(list);

        System.out.println(set1);
        System.out.println(set2);
        System.out.println(set3);
    }
}

[0, 1250, -41656, 1000, 555, -13]
[1000, -13, 0, -41656, 1250, 555]
[-41656, -13, 0, 555, 1000, 1250]

TreeMap 同理。
它们使⽤ Comparable 约定,认为排序相等的元素相等。

三、Guava

Google 开源的 Guava 提供了 JDK 没有的额外方法,不要重复发明轮⼦,尽量使⽤经过实战检验的类库。

  • Lists/Sets/Maps
  • ImmutableMap/ImmutableSet
  • Multiset/Multimap
  • BiMap
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359