一枚c/c++程序员java探索-容器

网上找了一张图,可以整个概况容器的整个结构

容器概念

容器接口是容器的基础。使用接口可以将容器的实现与容器接口分开,因而可以使用相同的方法访问容器而不需关心容器具体的数据结构。Iterator接口也使用户能够使用相同的方法访问不同的容器类。

容器API

  1. Collection 接口,定义了存取一组对象的方法,其子接口set和list分别定义了存储方式
    • Set中的数据对象没有顺序且不可重复
    • List中的数据对象有顺序且可以重复(equals)
  2. Map接口定义了存储“键(key) –值(value)映射对”的方法(一对一对往里装)

Collection接口中所定义的方法

1
2
3
4
int size() //装了多少个元素
boolean isempty() //是不是为空
void clear() //清空
boolean contains(object element) //是不是包含某个对象

容器类对象在调用remove,contains等方法时需要比较对象是否相等,这回涉及到对象类型的equals方法和hashcode方法,对于自定义的类型,需要重写equals和hashcode方法以实现自定义的对象相等规则(相等的对象应该具有相等的hash codes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class BaseColl {
public static void main(String[] args) {
Collection<Comparable> c = new HashSet<>();
c.add("hello");
c.add(new Name("f1","l1"));
c.add(100);
c.remove("hello");
c.remove(100);
System.out.println(c.remove(new Name("f1","l1")));
System.out.println(c);
}
}
class Name implements Comparable<Name>{
private String firstName,lastName;
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Name) {
Name name = (Name) obj;
return (firstName.equals(name.firstName)) && (lastName.equals(name.lastName));
}
return super.equals(obj);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String toString() {
return firstName + " " + lastName;
}
@Override
public int hashCode() {
return lastName.hashCode();
}
@Override
public int compareTo(Name o) {
return this.equals(o) ? 0 : -1;
}
}

Iterator接口

所有实现了collection接口的容器类都有一个iterator方法用返回一个实现了iterator接口对象
Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作

1
2
3
4
5
6
7
8
9
10
11
12
//通过集合的iterator方法,取得迭代器的实例
LinkedList<Name> lists = new LinkedList<>();
lists.add(new Name("jason", "hu"));
lists.add(new Name("jim", "li"));
lists.add(new Name("kobe", "Bryant"));
lists.add(new Name("Stephen","Curry"));
Iterator<Name> it = lists.iterator();
while(it.hasNext()) {
Name name = it.next();
System.out.println("name.first: " + name.firstName + ":" + name.lastName);
}

Collections

Collections工具类提供了大量针对Collection/Map的操作,总体可分为四类,都为静态(static)方法:

排序

  • reverse(List list):反转指定List集合中元素的顺序
  • shuffle(List list):对List中的元素进行随机排序(洗牌)
  • sort(List list):对List里的元素根据自然升序排序
  • sort(List list, Comparator c):自定义比较器进行排序
  • swap(List list, int i, int j):将指定List集合中i处元素和j出元素进行交换
  • rotate(List list, int distance):将所有元素向右移位指定长度,如果distance等于size那么结果不变

查找和替换

  • binarySearch(List list, Object key):使用二分搜索法,以获得指定对象在List中的索引,前提是集合已经排序
  • max(Collection coll):返回最大元素
  • max(Collection coll, Comparator comp):根据自定义比较器,返回最大元素
  • min(Collection coll):返回最小元素
  • min(Collection coll, Comparator comp):根据自定义比较器,返回最小元素
  • fill(List list, Object obj):使用指定对象填充
  • frequency(Collection Object o):返回指定集合中指定对象出现的次数
  • replaceAll(List list, Object old, Object new):替换

同步控制

Collections工具类中提供了多个synchronizedXxx方法,该方法返回指定集合对象对应的同步对象,从而解决多线程并发访问集合时线程的安全问题。HashSet、ArrayList、HashMap都是线程不安全的,如果需要考虑同步,则使用这些方法。这些方法主要有:synchronizedSet、synchronizedSortedSet、synchronizedList、synchronizedMap、synchronizedSortedMap。

特别需要指出的是,在使用迭代方法遍历集合时需要手工同步返回的集合。

1
2
3
4
5
6
7
8
9
Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized (m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}

设置不可变集合(TODO)

常见的容器比较

ArrayList VS LinkedList

  1. 因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很大的,因为这需要重排数组中的所有数据。
  2. 相对于ArrayList,LinkedList插入是更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索引(除了插入数组的尾部)。
  3. 类似于插入数据,删除数据时,LinkedList也优于ArrayList。
  4. LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。

    concurrent(TODO)

    JDK5之后新增的java.util.concurrent包下的集合类
JasonThink wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!