Java-集合的简单介绍

上周极度颓废,很咸鱼,就没有做开发学习的周记,这一周把Java核心技术卷I(除了swing等图形界面一块)看完了,然后开始看大话数据结构同时MOOC的数据结构也跟上,那就来总结总结Java里的集合这个和数据结构紧密联系的东西。
阅读体验较差可前往掘金:https://juejin.im/post/5cb0cecc5188251ad87b1685

1. Java集合框架

下图来自Java核心技术卷I(第10版)

1.1 集合框架的接口

上面的类看起来非常之多但是你仔细看看后面的单词末尾都会有一些相似的地方,Java的集合类库将接口和实现分离。如果你有接口的概念,那么看看下面的图可能就明白了。

上图我们可以看到除了Iterator(迭代器)不属于集合类的范畴外,所有的集合类都由两个基本的接口:Collection和Map。

1.2 Collection接口

Collection接口中定义的方法
这些方法非常好理解而且ArrayList里用过了很多,不多赘述。

Tips:只研究蓝色区域内的方法,默认方法不讨论

1.2.1 迭代器

通过上图的 iterator 方法来返回一个该集合的迭代器。
迭代器有什么用呢,我们来看看迭代器接口的方法
迭代器接口中的方法
方法很少但是在Collection却很重要。不多bb,上图
迭代器工作示意图
所以我们有如下的使用方法

1
2
3
for(Iterable<T> element : c){
// do something with element
}

将一个实现了Iterable接口的一个对象传入进行遍历,在这里这个对象就是我们说的实现了Collection接口的对象(因为Collection接口同时实现了Iterable接口)
remove方法就是删除 next 方法返回的对象

Tips: 不能连续使用两次remove方法来实现连续删除两个元素,应该使用next方法后再remove

1.2.2 Collection子接口——List

List是一个有序的集合,访问其中的元素既可以使用迭代器,也可以使用随机访问(即通过制定的索引访问)
List接口中定义的方法
继承自Collection接口,同时增添一些关于随机访问的方法

1
2
3
4
5
addAll(index:int, c:Collection<? extends E>):boolean
get(index:int):E
set(index:int, element:E):E
add(index:int, element:E)void
//......

经常使用ArrayList的同学肯定对这些方法不陌生。

1.2.3 Collection子接口——Set(集)

Set接口等同于Collection接口(没有增添新的方法),不过集(Set)的add方法不允许添加重复的元素。
Set接口add方法的官方描述,其中指出了Set接口的元素不相同的特性

1.2.3 Collection的子接口——Queue(队列)

首先我们来看看Queue接口中定义的方法
Queue接口中定义的方法
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。以下列出Queue新增的方法

1
2
3
4
5
offer(e:E):boolean//在队列尾部添加一个元素
remove():E//删除队列的头元素并返回,没有则抛出NoSuchElementException异常
poll():E//删除队列的头元素并返回,没有则返回null
element():E//返回队列头部元素,没有则抛出NoSuchElementException异常
peek():E//返回队列头部元素,没有则返回null

1.3 Map 接口

Map接口中定义的方法
这些方法和Collection不少有些相似,但是由于和Collection实现的方式有根本上的差异(1.4),所以总体来说还是很不一样的所以分成了两个接口。

Tips:只研究蓝色区域内的方法,默认方法不讨论

1.3.1 Map子接口——SortedMap

SortedMap是一个可以保证按照键的升序排列的映射,可以按照键的自然顺序(参见 Comparable 接口)进行排序, 或者通过创建有序映射时提供的比较器进行排序。
上图:
SortedMap接口中定义的方法

1.4 Collection和Map实现的差异

Collection添加元素的时候一般只需要提供要传入的元素,而Map是需要以键值对的方式(Key/Value)来添加的,一个Key对应一个Value。所以才导致了一些方法的不同

2. 具体的集合(Collection)



需要指出的是,我们现在所用的集合类都是继承自Abstract+List/Set/Queue/Map抽象类而不是实现了某些接口,但是这些抽象类同样实现了对应的接口,其实还是间接实现了对应的接口,但是使用继承抽象类来实现集合类的话会比较方便。
下面介绍几种常用的集合类,偏向介绍特性一些简单的使用就忽略了。

2.1 ArrayList

  • 继承自AbstractList
  • 根据名字可以理解为一种常用的长度可变的数组(?)
  • 也是使用的比较多一种集合,使用起来比较简单,方便,不多赘述

    2.2 LinkedList

  • 继承自AbstractSequentialList
  • 实际上是一种双向链表(参见 数据结构—链表)

在C++里我们通过不停地变换指针来到我们需要的节点然后进行增删改查,在Java里,我们使用迭代器来进行增删改查的操作。这里我们使用的迭代器不是原来我们介绍的迭代器,而是另一个,Iterator的子接口ListIterator。
ListIterator
其中有一个新的词Previous(前者),对比next你就可以理解这些新的方法的含义。所以说Java中的链表默认是双向的(你想自己实现一个单项的也行233333333)
简答举例就可以理解:

1
2
3
4
5
6
7
8
9
10
List<String> food = new LinkedList<>();
food.add("翅桶");
food.add("春日全家桶");
food.add("书亦烧仙草");
ListIterator<String> listIterator = food.listIterator();
listIterator.next();//翅桶
listIterator.add("重庆鸡公煲");//翅桶,重庆鸡公煲,春日全家桶,书亦烧仙草
listIterator.next();//春日全家桶
listIterator.remove();//翅桶,重庆鸡公煲,书亦烧仙草
listIterator.previous();//重庆鸡公煲

2.3 ArrayDeque

  • 继承自AbstractCollection并实现了Deque接口
  • 是一种用循环数组实现的双端队列
    ArrayDeque实现的部分方法
    我们从方法名来看,并比对1.2.3的Deque(队列)接口中的方法,不难看出它的使用方法。实际上就是一个可以从头部添加或者删除的队列,但依然不允许从中间添加或者删除元素,即使有迭代器,并有remove的方法,但是实际上依然remove方法依然是删除头部的元素:
    ArrayDeque中的remove方法
    同理,所有继承自Collection的方法所对应的操作都是把它当做普通的队列来操作。

    2.4 HashSet

  • 继承自AbstractSet
  • 用来存放没有重复元素的无序集合
  • 基于HashMap实现
    AbstractSet的部分方法
    巧妙的是,为了做到没有重复元素,该集(Set)底层是通过新建一个HashMap并将元素当做HashMap的key的原理实现的,因为HashMap的key是独一无二的。有关HashMap的描述,后面会讲到。
    无序集合采用迭代器的方式遍历整个元素,无法决定顺序,但是总会遍历完所有的元素。

2.5 TreeSet

  • 继承自AbstractSet
  • 用来存放没有重复元素的有序集合
  • 基于HashTree实现
    TreeSet中的部分方法
    first和last返回的是第一和最后一个元素
    lower返回的是严格比给定元素要小的最大元素
    floor返回的是比给定元素小于或等于的最大元素
    higher返回的是严格比给定元素要大的最小元素
    ceiling返回的是比给顶元素大于或者等于的最小元素
    pollFirst/Last将集(Set)的头部/尾部元素删除(弹出)并返回
    同样是使用HashTree中的key值唯一性来保证没有重复的元素。

3. 具体的映射(Map)

Tips:注意映射和集合

3.1 HashMap

  • 继承自AbstractMap
  • 一种储存键值对的无序数据结构
    HashMap包含的部分方法
    使用其实也非常容易理解,首先,他是无序的,迭代器访问的时候也是随机、无序的。往HashMap放一个值的时候就要把键(key)值(value)对都传给put方法,想要访问元素的时候呢就需要拿到他的key。还可以通过keySet方法和values方法单独得到key和value的Collection对象。其中关于HashMap更多的细节,我还不是特别清楚,以后会继续讨论√
  • 对象和key必须是一一对应的,如果你想对自定义类放入HashMap,那你必须重写hashCode方法来生成对象的key,还要重写equals方法以保证两个hashCode相等的对象返回的是false。

3.2 TreeMap

  • 继承自AbstractMap
  • 一种储存键值对的有序数据结构
  • 排序的底层实现为红黑树(red-black tree)
    TreeMap的部分方法
    使用起来和HashMap看起来差不多,区别就在于一个有序一个无序,迭代器总是能够以排好的顺序依次访问元素。

3.总结

突然不想写了,感觉写这些简单的没什么深度,看了清夏学姐推荐的GitBook发现自己是真的弟。。。。。。
从今以后我写的会更加注重深层次的东西,不在于多,而在于深。
不多bb,看书去了√