第十一章 持有对象

持有对象:容器,具有动态大小,比如List,Queue,Map,Set

Collection

Collection 是一个接口,Map,Set,List等容器都是在实现它的接口的基础上实现的.

tip:Collectionsjava.util.*中的类,有很多实用方法

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Collection接口函数如下:
Collection<Integer> collection = new Collection<Integer>() {
@Override
public <T> T[] toArray(T[] a) {
// TODO Auto-generated method stub
return null;
}

@Override
public Object[] toArray() {
// TODO Auto-generated method stub
return null;
}

@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}

@Override
public boolean retainAll(Collection<?> c) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean removeAll(Collection<?> c) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean remove(Object o) {
// TODO Auto-generated method stub
return false;
}

@Override
public Iterator<Integer> iterator() {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean containsAll(Collection<?> c) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean contains(Object o) {
// TODO Auto-generated method stub
return false;
}

@Override
public void clear() {
// TODO Auto-generated method stub

}

@Override
public boolean addAll(Collection<? extends Integer> c) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean add(Integer e) {
// TODO Auto-generated method stub
return false;
}
};

可以通过Collection方法来实现构建一个Collection对象

一般,我们都是将List,Map等容器向上转型成Collection.

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
package Chapter11;

import java.util.*;

public class ttt {
public static void main(String args[]){
/*
* 将Linkedlist 向上转型为Collection
*/
Collection<Integer> collection = new LinkedList<Integer>();
List<Integer> arr = Arrays.asList(1,2,3,4,5,6);
/*
* addAll()
*/
collection.addAll(arr);
System.out.println(collection);
/*
* add()
*/
collection.add(55);
System.out.println(collection);
/*
* 判断是否包含某个元素
* contains()
*/
System.out.println("是否包含1: "+collection.contains(1));
Collection<Integer> collection2 = new LinkedList<Integer>();
List<Integer> arr1 = Arrays.asList(4,3,2,1);
collection2.addAll(arr1);
/*
* containsAll
*/
System.out.println("是否包含子容器"+collection.containsAll(collection2));
/*
* remove
*/
collection.remove(1);
System.out.println(collection);

}

}
1
2
3
4
5
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 55]
是否包含1: true
是否包含子容器true
[2, 3, 4, 5, 6, 55]

迭代器

利用好迭代器,就无需知道容器类型,也可达到遍历容器内元素,并进行相关操作

Java的迭代器Iterator只能单向移动:

  • 利用容器.iterator()要求容器返回一个迭代器iterator
  • .next() 获得序列的下一个元素
  • .hasNext() 判断是否有下一个元素
  • .remove() 移除当前所指向的元素

tip: 在容器返回一个迭代器iterator时,初始时它指向第一个元素的前面,因此iterator.next()可以获得容器中的第一个元素.

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
package Chapter11;

import java.util.*;

public class ttt {
public static void main(String args[]){
/*
* 将Linkedlist 向上转型为Collection
*/
Collection<Integer> collection = new LinkedList<Integer>();
List<Integer> arr = Arrays.asList(1,2,3,4,5,6);
/*
* addAll()
*/
collection.addAll(arr);
System.out.println(collection);
Iterator<Integer> iterator = collection.iterator();
System.out.println("iterator.next(): "+iterator.next());
/*
* 输出除第一个元素外的剩余元素
*/
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Iterator<Integer> iterator2 = collection.iterator();
/*
* 移除元素
*/
iterator2.next();
iterator2.remove();
System.out.println(collection);


}

}
1
2
3
4
5
6
7
8
[1, 2, 3, 4, 5, 6]
iterator.next(): 1
2
3
4
5
6
[2, 3, 4, 5, 6]

利用iterator 实现输出不同容器类型

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
package Chapter11;

import java.util.*;

class PrintCollection{
public static void printCollection(Iterator it){
System.out.println("输出容器内元素");
while(it.hasNext()){
System.out.println(it.next());
}
}
}

public class ttt {
public static void main(String args[]){
/*
* 将Linkedlist 向上转型为Collection
*/
Collection<Integer> collection = new LinkedList<Integer>();
List<Integer> arr = Arrays.asList(1,2,3,4,5,6);
/*
* addAll()
*/
collection.addAll(arr);
System.out.println(collection);
Iterator<Integer> iterator = collection.iterator();

PrintCollection.printCollection(iterator);
/*
* 新建一个String 类型的 set
*/
Collection<String> collection2 = new HashSet<String>();
String string = "Hello World!";
List<String> arr2 = Arrays.asList(string.split(""));
collection2.addAll(arr2);
System.out.println("collection2: "+collection2);
Iterator<String> iterator2 = collection2.iterator();
PrintCollection.printCollection(iterator2);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[1, 2, 3, 4, 5, 6]
输出容器内元素
1
2
3
4
5
6
collection2: [ , !, r, d, e, W, H, l, o]
输出容器内元素

!
r
d
e
W
H
l
o

Linkedlist

利用LinkedList自定义栈

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
package Chapter11;
import java.util.LinkedList;;

class Stack<T>{
private LinkedList<T> storage = new LinkedList<T>();
public void push(T v){
storage.add(v);
}
public T pop(){
return storage.removeLast();
}
/*
* get top of stack
*/
public T peek(){
return storage.getFirst();
}
public boolean empty(){
return storage.isEmpty();
}
public String toString(){
return storage.toString();
}
}

public class Statckdemo {
public static void main(String args[]){
Stack<Integer> stack = new Stack();
for (int i=0;i<10;i++){
stack.push(i);
}
System.out.println(stack);
System.out.println("获得栈顶元素: "+stack.peek());
System.out.println("pop元素: "+stack.pop());
System.out.println("是否为空 : "+stack.empty());
}

}
1
2
3
4
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
获得栈顶元素: 0
pop元素: 9
是否为空 : false

书中介绍到: 尽管有java.util.Stack但是利用LinkedList可以产生更好的Stack

Set

set 有 HashSet,TreeSet,LinkedHashSet,适用于归属性查询,

  • HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;
  • LinkedHashSet:以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代;
  • TreeSet:提供一个使用红黑树结构存储Set接口的实现,对象以升序顺序访问和遍历的时间很快。(其结果是有序的,默认升序)
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
package Chapter11;
import java.util.*;
public class SetDemo {

public static void main(String args[]){
/*
* HashSet,用于判断元素是否存在,无序,查找速度快,使用散列
*/
Set<String> set1 = new HashSet<String>();
Collections.addAll(set1 , "c b a d e f g h k".split(" "));
System.out.println("set1---------- "+set1);
/*
* 判断 h 是否在set1中
*/
System.out.println("H in set1: " + set1.contains("H"));
Set<String> set2 = new HashSet<String>();
Collections.addAll(set2, "a b c d e".split(" "));
/*
* 判断set2 是否在set1 中
*/
System.out.println("set2 in set1: "+ set1.containsAll(set2));

/*
* TreeSet : 有序,存储在红黑树中,下面例子中对TreeSet进行排序
* TreeSet 可与 SortedSet 结合使用进行排序
*/
SortedSet<String> sortedSet = new TreeSet<String>();
Collections.addAll(sortedSet, "c b a d e f g h k".split(" "));
System.out.println("sortedSet-------- "+sortedSet);

/*
* LinkedHashSet: 兼具列表特性,以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代
* 下面例子,在相同的插入顺序情况下,比较各个Set的最终顺序
*/
Set<String> hashSet2 = new HashSet<String>();
Set<String> linkedHashSet2 = new LinkedHashSet<String>();
Set<String> treeSet2 = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
Set<String> treeSet3 = new TreeSet<String>();
String[] strings = new String[]{"q","A","B","w ","e ","r ","t ","y ","u ","i ","o ","p ","a ",""
+ "s ","d ","f ","g ","h ","j ","k ","l ","z ","x ","c ","v ","b ","n ","m"};
for (String string : strings) {
hashSet2.add(string);
linkedHashSet2.add(string);
treeSet2.add(string);
treeSet3.add(string);
}
/*
* 输出
* 字典序:大小写被分成不同的组中
*/
System.out.println("hashSet2 "+hashSet2);
System.out.println("linkedHashSet2 "+linkedHashSet2);
System.out.println("treeSet2(字母序) "+treeSet2);
System.out.println("treeSet3(字典序) "+treeSet3);
}
}

结果

1
2
3
4
5
6
7
8
set1----------  [a, b, c, d, e, f, g, h, k]
H in set1: false
set2 in set1: true
sortedSet-------- [a, b, c, d, e, f, g, h, k]
hashSet2 [A, B, y , w , u , s , o , k , i , g , e , c , a , z , x , v , t , m, r , p , q, n , l , j , h , f , d , b ]
linkedHashSet2 [q, A, B, w , e , r , t , y , u , i , o , p , a , s , d , f , g , h , j , k , l , z , x , c , v , b , n , m]
treeSet2(字母序) [A, a , B, b , c , d , e , f , g , h , i , j , k , l , m, n , o , p , q, r , s , t , u , v , w , x , y , z ]
treeSet3(字典序) [A, B, a , b , c , d , e , f , g , h , i , j , k , l , m, n , o , p , q, r , s , t , u , v , w , x , y , z ]

可知,HashSet是无序的,LinkedHashSet的顺序取决与插入顺序,TreeSet默认升序排序

Tip:通过向TreeSet构造器中传入String.CASE_INSENTIVE_ORDER比较器,实现字母序排序

Map

如下代码,展示如何创建一个HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package Chapter11;
import java.util.*;
public class MapDemo {
public static void main(String args[]){
Random random = new Random(50);
/*
* Map 中的key和value必须为包装器类型
* 比如不能为int ,可以为Integer
*/
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for ( int i=0; i<1000;i++){
int key = random.nextInt(20);
/*
* Value 必须为Integer,否则它不能与null进行比较
*/
Integer value = map.get(key);
map.put(key, value==null ? 1 : value + 1);
}
System.out.println(map);
}

}

结果

1
{0=50, 1=43, 2=46, 3=59, 4=51, 5=50, 6=55, 7=51, 8=51, 9=55, 10=54, 11=51, 12=55, 13=51, 14=53, 15=45, 16=51, 17=45, 18=46, 19=38}

下面是Map接口的方法

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Map<Integer, Integer> map = new Map<Integer, Integer>() {
@Override
public Collection<Integer> values() {
// TODO Auto-generated method stub
return null;
}

@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}

@Override
public Integer remove(Object key) {
// TODO Auto-generated method stub
return null;
}

@Override
public void putAll(Map<? extends Integer, ? extends Integer> m) {
// TODO Auto-generated method stub

}

@Override
public Integer put(Integer key, Integer value) {
// TODO Auto-generated method stub
return null;
}

@Override
public Set<Integer> keySet() {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}

@Override
public Integer get(Object key) {
// TODO Auto-generated method stub
return null;
}

@Override
public Set<Entry<Integer, Integer>> entrySet() {
// TODO Auto-generated method stub
return null;
}

/*
* 判断值是否存在
*/

@Override
public boolean containsValue(Object value) {
// TODO Auto-generated method stub
return false;
}

/*
* 判断键是否存在
*/

@Override
public boolean containsKey(Object key) {
// TODO Auto-generated method stub
return false;
}

@Override
public void clear() {
// TODO Auto-generated method stub

}
};

Queue

队列(Queue),先进先出,能完成的保存队列的顺序,存入的顺序与取出的顺序相同,因此,队列适合用于多线程编程

,因为LinkedList实现的Queue的接口,可将LinkedList向上转型成Queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Chapter11;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class QueueDemo {
public static void main(String args[]){
Queue<Integer> queue = new LinkedList<>();
Random random = new Random(99);
for (Integer i=0;i<10;i++){
queue.offer(random.nextInt(i+10));
}
System.out.println(queue);
}
}

输出

1
[7,10,9,8,8,2,13,0,14,4]

以下是Queue的方法

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Queue<Integer> queue = new Queue<Integer>() {

@Override
public boolean addAll(Collection<? extends Integer> arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public void clear() {
// TODO Auto-generated method stub

}

@Override
public boolean contains(Object arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean containsAll(Collection<?> arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}

@Override
public Iterator<Integer> iterator() {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean remove(Object arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean removeAll(Collection<?> arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean retainAll(Collection<?> arg0) {
// TODO Auto-generated method stub
return false;
}

@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}

@Override
public Object[] toArray() {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> T[] toArray(T[] arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean add(Integer e) {
// TODO Auto-generated method stub
return false;
}

@Override
public Integer element() {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean offer(Integer e) {
// TODO Auto-generated method stub
return false;
}

@Override
public Integer peek() {
// TODO Auto-generated method stub
return null;
}

@Override
public Integer poll() {
// TODO Auto-generated method stub
return null;
}

@Override
public Integer remove() {
// TODO Auto-generated method stub
return null;
}
};


  • public boolean add(Integer e) : 添加元素到队尾
  • public Integer remove() : 移除队头并返回队头元素,若队列为空,抛出异常
  • public Integer element() : 在不移除的情况下返回队头,若队列为空,则抛出异常

  • public boolean offer(Integer e) : 在允许的情况下,将元素插入队尾,其返回值是布尔类型
  • public Integer peek() : 返回队头元素,若队列为空,则返回null
  • public Integer poll() : 移除并返回队头元素,若队列为空,则返回null

add(),remove(),element()在出现差错(要移除的元素不存在等情况),会抛出异常,其中,remove和element会抛出NoSuchElementException异常

PriorityQueue(优先队列)

Queue可以看做将出入队列时间当做优先级排序规则的优先队列

优先队列可以自主设定队列规则,先弹出的元素总是优先级最高的元素

PriorityQueue创建的几种方式

  • 新建一个空队列,利用add,offer,创建
  • 新建一个空队列,利用addAll创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Chapter11;
import java.util.*;
public class QueueDemo {
public static void main(String args[]){
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
/*
* 创建一个列表
*/
List<Integer> list = Arrays.asList(2,3,3,11,2,66,5,4,8);
/*
* 将列表里的值通过addAll方法传入到优先队列中
*/
priorityQueue.addAll(list);
System.out.print(priorityQueue);
}

}
1
[2, 2, 3, 4, 3, 66, 5, 11, 8]
  • 在构造函数中创建,在构造函数中传入列表
1
2
3
4
5
6
7
8
9
10
package Chapter11;
import java.util.*;
public class QueueDemo {
public static void main(String args[]){
List<Integer> list = Arrays.asList(2,3,3,11,2,66,5,4,8);
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>(list);
System.out.print(priorityQueue);
}

}
1
[2, 2, 3, 4, 3, 66, 5, 11, 8]
  • 在构造函数中创建,可以传入队列长度优先级比较规则,创建一个指定大小的空队列
1
2
3
4
5
6
7
8
9
10
11
package Chapter11;
import java.util.*;
public class QueueDemo {
public static void main(String args[]){
List<Integer> list = Arrays.asList(2,3,3,11,2,66,5,4,8);
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>(list.size(),Collections.reverseOrder());
priorityQueue.addAll(list);
System.out.print(priorityQueue);
}

}
1
[66, 8, 11, 4, 2, 3, 5, 2, 3]

本文标题:第十一章 持有对象

文章作者:定。

发布时间:2017年7月18日 - 13时07分

本文字数:14,214字

原始链接:http://cocofe.cn/2017/07/18/第十一章 持有对象/

许可协议: Attribution-NonCommercial 4.0

转载请保留以上信息。