1.1集合框架的优点
传统的容器(数组)在进行增、删等破坏性操作时,需要移动元素,可能导致性能问题;同时添加、删除等算法和具体业务耦合在一起,增加了程序开发的复杂度。
Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中
2.2Collection
Collection是java集合框架(collection-frame)中的顶层接口。
Collection接口是一个容器,容器中只能存储引用数据类型,建议存同一类型的引用类型,方便后续遍历等操作。
容器中的元素可以是有序的、可重复的,称为List接口
也可能是无序的、唯一的,称为Set接口。
1.2.1 集合的常用方法
* 增:add/addAll
* 删:clear/remove/removeAll/retainAll
* 改:
* 查:contains/containsAll/isEmpty/size
1 public static voidmain(String[] args) {2
3 /**
4 * 增:add/addAll5 * 删:clear/remove/removeAll/retainAll6 * 改:7 * 查:contains/containsAll/isEmpty/size8 */
9
10 Collection c1 = newArrayList();11
12 //追加
13 c1.add("apple"); //Object object = new String("apple");14 //c1.add(1);//Object object = new Integer(1);
15 c1.add("banana");16 System.out.println(c1);17
18 //追加一个集合
19 Collection c2 = newArrayList();20 c2.add("java");21 c2.add("c++");22 c1.addAll(c2);23 System.out.println(c1);24
25 //clear26 //c1.clear();27
28 //c1.remove("apple");29 //c1.removeAll(c2);30 //c1.retainAll(c2);31 //System.out.println(c1);
32
33 System.out.println(c1.contains("apple"));34 c2.add("js");35 System.out.println(c1.containsAll(c2));36 //c1.clear();
37 System.out.println(c1.isEmpty());38 //返回集合元素的个数
39 System.out.println(c1.size());40
41 System.out.println(c1.equals(c2));42
43 }
1.2.2集合的遍历
关键字:Iterable
Iterable 可遍历的接口,集合接口继承于它,集合支持快速遍历。
//快速遍历//for-each//Object 表示元素类型//item表示迭代变量//c1表示集合
for(Object item : c1) {
System.out.println(item.toString());
}
快速遍历的本质
Collection继承于Iterable接口,表示集合支持快速遍历。Iterable接口定义了一个方法iterator()用于获取集合的迭代器,是一个Iterator接口类型,iterator()内部返回一个实现类实现类Iterator接口。这个实现类一定具有hasNext和next方法用于判断是否有下一个元素和获取下一个元素。快速遍历就是基于迭代器工作的。
1 public static voidmain(String[] args) {2
3
4 Collection c1 = newArrayList();5 c1.add("apple");6 c1.add("banana");7 c1.add("coco");8
9
10 //快速遍历11 //for-each12 //Object 表示元素类型13 //item表示迭代变量14 //c1表示集合
15 for(Object item : c1) {16 System.out.println(item.toString());17 }18
19 //迭代器遍历(国内)
20 Iterator it =c1.iterator();21 while(it.hasNext()) {22 Object item =it.next();23 System.out.println(item.toString());24 }25
26 //国外
27 for(Iterator it2=c1.iterator();it2.hasNext();) {28 Object item =it2.next();29 System.out.println(item.toString());30 }31 }
1.3 List接口
List 接口中的元素时有序的、可重复的。List接口中的元素通过索引(index)来确定元素的顺序。
有序的 collection(也称为序列)。可以对列表中每个元素的插入位置进行精确地控制。
用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素
1.3.1 List常用方法
增:add/addAll/add(index,el)/addAll(index,collection)
删:clear/remove/removeall/remove(index)
改:set(index,el)
查:get(index)/indexOf/lastIndexOf()
其他:contains/containsall/isEmpty/size
1 public static voidmain(String[] args) {2
3 /**
4 * 增:add/addAll/add(index,el)/addAll(index,collection)5 * 删:clear/remove/removeAll/remove(index)6 * 改:set(index,el)7 * 查:get(index)/indexOf/lastIndexOf()8 * 其他:contains/containsAll/isEmpty/size9 */
10 List list1 = newArrayList();11 //添加元素
12 list1.add("apple");13 list1.add("banana");14 //在指定位置添加元素
15 list1.add(0, "coco");16
17 System.out.println(list1);18
19 List list2 = newArrayList();20 list2.add("java");21 list2.add("c++");22
23 list1.addAll(1, list2);24 System.out.println(list1);25
26 //删除
27 list1.remove(0);28 System.out.println(list1);29
30 //修改
31 list1.set(0, "javax");32 System.out.println(list1);33
34 //查
35 System.out.println(list1.get(0));36 list1.add("apple");37 list1.add("apple");38 System.out.println(list1);39 System.out.println(list1.indexOf("apple"));40 System.out.println(list1.lastIndexOf("apple"));41 }
1.3.2 接口遍历
ListIterator继承于Iterator,在Itertaor的基础上提供了以正向遍历集合,也可以以遍历集合。
hasNext/ next 以正向 遍历
hasPrevious/previous 以遍历
【1】for each 遍历
【2】普通for遍历
【3】集合迭代器遍历
(1)正向遍历
(2)逆向遍历
1 public static voidmain(String[] args) {2
3
4 List list1 = newArrayList();5 list1.add("apple");6 list1.add("banana");7 list1.add("coco");8
9 //【1】快速遍历
10 System.out.println("--for each--");11 for(Object item : list1) {12 System.out.println(item.toString());13 }14
15 //【2】普通for
16 System.out.println("--for--");17 for(int i=0;i
21 //【3】集合迭代器
22 System.out.println("--iterator--");23 Iterator it =list1.iterator();24 while(it.hasNext()) {25 System.out.println(it.next());26 }27
28 System.out.println("--list iterator--");29 //正向遍历
30 ListIterator it2 =list1.listIterator();31 while(it2.hasNext()) {32 System.out.println(it2.next());33 }34
35 //逆序遍历
36 while(it2.hasPrevious()) {37 System.out.println(it2.previous());38 }39
40 System.out.println("--list iterator with index--");41 ListIterator it3 = list1.listIterator(1);42 while(it3.hasNext()) {43 System.out.println(it3.next());44 }45 }
1.4 数据结构
1.4.1线性表
线性表数据按照一定的逻辑顺序存储在内存中。线性表是有序的。线性表根据内存的物理结构分为两种:数组和链表
数组是一种逻辑上有序的线性表,物理上也连续。
链表是一种逻辑上有序的线性表,但物理上不连续。
数组和链表的区别:
相同点:逻辑上有序
不同点:数组是物理上有序的,链表是物理上无序的。
数组在查询时效率高,在添加、删除元素时效率低(涉及移动元素)
链表在查询时效率低(每次从头开始,不能跳跃访问),在添加、删除元素时效率高(不涉及移动元素)
1.4.2 栈
特性:先进后出,后进先出
1.4.3 队列
特性:先进先出
1.5 ArrayList/Vector
ArayList 是List接口的实现类,底层数据结构是数组,实现大小可变的数组。
ArrayList 线程不安全,jdk1.2
ArrayList底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,
ArrayList会自动拓容,拓容原则:newCapacity = oldCapacity + oldCapacity / 2(oldCapacity>>1);
如果未来确定序列的元素不再增加,通过trimTosize()调制容量至合适的空间。
ArrayList 作为List接口的实现类,常用方法和遍历方法参考List接口。
Vector 是List接口的实现类,底层数据 结构也是数组 ,也是大小可变的数组 。
Vector是线程安全的,jdk1.0
Vector底层数据结构是数组,默认数组大小是10,
如果添加的元素个数超过默认容量,Vector会自动拓容,拓容原则:newCapacity = oldCapacity +capacityIncrement(增长因子);如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。
注意:Vector 在实现List接口的同时,同添加了自身特有的方法xxxElement,未来使用时为了程序的可拓展性,一定要按照接口来操作Vector。
1.6 Linkedlist
LInkedLIst是LIst接口的实现类,底层数组结构是链表。
LinkedList常用方和遍历方法参照List接口。
LinkedList线程不安全。
LinkedList坠子实现List接口,还实现栈接口。
push入栈操作,pop出栈操作
1 public classTest01 {2 public static voidmain(String[] args) {3 LinkedList list = newLinkedList();4 list.push("apple");5 list.push("banana");6 list.push("coco");7
8
9 System.out.println(list.pop());10 System.out.println(list.pop());11 System.out.println(list.pop());12
13 //java.util.NoSuchElementException
14 System.out.println(list.pop());15 }16 }
队列(Queue)接口
add/remove/element()可能会出现NoSuchElementException异常
1 public static voidmain(String[] args) {2
3 LinkedList queue = newLinkedList();4 //入队
5 /**
6 * 队列头 队列尾7 *
10 queue.add("apple");11 queue.add("banana");12 queue.add("coco");13 System.out.println(queue);14
15 //出队
16 System.out.println(queue.remove());17 System.out.println(queue.remove());18 System.out.println(queue.remove());19 System.out.println(queue);20
21 //java.util.NoSuchElementException
22 System.out.println(queue.remove());23
24
25 //获取表头元素
26 System.out.println(queue.element());27 }
offer/poll/peek可能会返回特殊值(null)
1 public static voidmain(String[] args) {2
3 LinkedList queue = newLinkedList();4 //入队
5 /**
6 * 队列头 队列尾7 *
10 queue.offer("apple");11 queue.offer("banana");12 queue.offer("coco");13
14 //出队列15 //System.out.println(queue.poll());16 //System.out.println(queue.poll());17 //System.out.println(queue.poll());
18 System.out.println(queue);19
20 //System.out.println(queue.poll());21
22 //获取表头元素
23 System.out.println(queue.peek());24
25 }
双向队列(Deque)接口
1 /**
2 * 以双向队列形式操作LinkedList3 */
4 public classTest04 {5 public static voidmain(String[] args) {6
7 LinkedList queue = newLinkedList();8 //入队
9 /**
10 * ----->13 */
14
15 queue.addFirst("apple");16 queue.addFirst("banana");17 queue.addFirst("coco");18 System.out.println(queue);19
20 System.out.println(queue.removeLast());21 System.out.println(queue.removeFirst());22 System.out.println(queue.removeFirst());23 System.out.println(queue);24
25 //获取头元素
26 System.out.println(queue.getFirst());27
28 }29 }
1.7 Iterator和LIstiterator
Iterator在迭代过程中不允许向集合中添加元素
Listiterator可以在迭代过程中添加元素
1 public static voidmain(String[] args) {2 ArrayList list = newArrayList();3 list.add("apple");4 list.add("banana");5 list.add("coco");6
7 Iterator it =list.iterator();8 while(it.hasNext()) {9 String item =(String) it.next();10 if(item.equals("banana")) {11 list.add("test");12 }13 }14
15 System.out.println(list);16 }
当通过Iterator集合迭代器遍历集合过程中,不能再向集合汇总添加元素,否则出现ConcurrentModificationException 并发修改异常。
ListIterator允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。
1 public classTest01 {2 public static voidmain(String[] args) {3 ArrayList list = newArrayList();4 list.add("apple");5 list.add("banana");6 list.add("coco");7
8 ListIterator it =list.listIterator();9 while(it.hasNext()) {10 String item =(String) it.next();11 if(item.equals("banana")) {12 it.add("test");13 }14 }15
16 System.out.println(list);17 }18 }
1.8 泛型(generic)
1.8.1 反省的概念
泛型允许开发者在强类型程序设计 语言(java)编写代码时定义一些可变部分,这些部分在使用前必须作出指明。
泛型就是将类型参数化。
ArrayList list 表示声明了一个列表list,列表的元素是E类型。
ArrayList list = new ArrayList();
声明了一个列表list,列表的元素只能是String类型。
泛型在编译器起作用,运行时jvm察觉不到泛型的存在。
1.8.2 泛型的擦除
泛型在运行时已经被擦除了。
1 public static voidmain(String[] args) {2 ArrayList list = new ArrayList();3 list.add("apple");4 System.out.println(list instanceofArrayList);5 System.out.println(list instanceof ArrayList);//错的表达方式
6 System.out.println(list instanceof ArrayList>);//正确的表达方式
7 }
错误时的异常:
Cannot perform instanceof check against parameterized type ArrayList. Use the form ArrayList> instead since further generic type information will be erased at runtime
1.8.3 泛型的应用
1.8.3.1 泛型类
当一个类中属性的数据类型不确定时,具体是什么类型由开发者决定,使用泛型。泛型类的形式:
public class 类名{
}
定义一个泛型类
1 public class FanClass{2 privateT t;3
4 publicT getT() {5 returnt;6 }7
8 public voidsetT(T t) {9 this.t =t;10 }11
12 publicFanClass(T t) {13 super();14 this.t =t;15 }16
17 publicFanClass() {18 super();19 }20 }
1 public classTest01 {2 public static voidmain(String[] args) {3 FanClass fan = new FanClass();4 fan.setT("apple");5
6 FanClass fan2 = new FanClass();7 fan2.setT(1);8 }9 }
1.8.3.2 泛型方法
当现代战争方法的参数 类型不确定时,具体是什么类型由使用者来确定,可以考虑使用泛型方法。
形式:
【1】把类定义成泛型类,如下:
public voidxxx(T a) {
System.out.println(a);
}
【2】
1 public classStudent {2
3
4 /*public void showInfo(int a) {5 System.out.println(a);6 }7
8 public void showInfo(float a) {9 System.out.println(a);10 }11
12 public void showInfo(String a) {13 System.out.println(a);14 }*/
15
16 public voidshowInfo(T a) {17 System.out.println(a);18 }19 }
1 public static voidmain(String[] args) {2
3 Student stu = newStudent();4 stu.showInfo(1);5 stu.showInfo("apple");6 stu.showInfo(1.0f);7 }
泛型方法在调用时确定(指明)类型。
泛型方法在一定程度上优化了方法重载。
泛型方法可以定义多个泛型类型
1 //可以定义多个泛型的类型
2 public voidshowInfo(A a,B b) {3 System.out.println(a);4 System.out.println(b);5 }
多个泛型类型进一步优化了方法重载。
多个同类型的泛型
1 //多个同类型的泛型
2 /*public void print(A a) {3 System.out.println(a);4 }5 public void print(A a,A b) {6 System.out.println(a);7 System.out.println(b);8 }*/
9
10 public voidprint(A...a) {11 System.out.println(a);12 }
A… a 表示方法可以接受多个参数。当调用方法传递多个参数时,多个参数被放到a数组中,a是什么类型的数组由开发者调用处传参决定。
1 stu.print(1);2 stu.print(1,2);3
4 stu.print("apple");5 stu.print("apple","banana");
print(A...a) 方法称为可变参数的泛型形式。
2.1.1.1 泛型接口(C)
如果接口中的方法的参数(形参、返回值)不确定时,可以考虑使用泛型接口。形式
1 public interface FanInterface{2
3 public voidshowInfo(T t);4
5 }
[1]实现类能确定泛型接口的类型
1 public class ImplClass implements FanInterface{2
3 @Override4
5 public voidshowInfo(String t) {6
7 //TODO Auto-generated method stub
8
9 }10
11 }
[2]实现类不能确定泛型接口的类型->继续泛。
1 public class ImplClass2 implements FanInterface{2
3 @Override4
5 public voidshowInfo(T t) {6
7
8 }9
10 }
2.1.1.2 泛型的上限和下限(C)
1 public static void print(ArrayList extends Pet>list) {2
3 for(Pet pet : list) {4
5 pet.showInfo();6
7 }8
9 }
泛型的上限ArrayList extends Pet> list 声明了一个容器,容器中的元素类型一定要继承于Pet,我们称这种形式叫做泛型的上限。
泛型的下限ArrayList super Pet> list 声明了一个容器,容器中的元素类型一定要是Pet的父类,我们称这个形式为泛型的下限。
3.1 Set接口
Set接口表示一个唯一、无序的容器(和添加顺序无关)
3.1.1 Set接口提供的方法
1 public static voidmain(String[] args) {2
3 /**
4
5 * 增:add/addAll6
7 * 删:clear/remove/removeAll/retainAll8
9 * 改:10
11 * 查:contains/containsAll12
13 * 遍历:iterator14
15 * 其他:size/isEmpty16
17 */
18
19
20
21 Set set = new HashSet();22
23 //[1]添加24
25 //无序
26
27 set.add(10);28
29 set.add(3);30
31 set.add(20);32
33 set.add(0);34
35 //不能添加重复元素
36
37 boolean r = set.add(1);38
39 System.out.println(set);40
41
42
43 //【2】删除44
45 //set.remove(1);46
47 //set.clear();48
49 //System.out.println(set);50
51
52
53 //【3】查看是否包含
54
55 System.out.println(set.contains(1));56
57
58
59 //【4】其他
60
61 System.out.println(set.size());62
63 System.out.println(set.isEmpty());64
65 }
3.1.2 Set接口的遍历
1 public static voidmain(String[] args) {2
3
4 Set set = new HashSet();5
6 set.add("banana");7
8 set.add("apple");9
10 set.add("coco");11
12
13
14 //快速遍历
15
16 for(String item : set) {17
18 System.out.println(item);19
20 }21
22
23 //迭代器
24
25 Iterator it =set.iterator();26
27 while(it.hasNext()) {28
29 String item =it.next();30
31 System.out.println(item);32
33 }34
35 }
Set接口的实现类常见的有HashSet、LinkedHashSet、TreeSet
3.2 HashSet
HashSet是Set接口的实现类,底层数据结构是哈希表。
HashSet是线程不安全的(不保证同步)
3.2.1 哈希表工作原理
3.2.2 添加自定义对象
根据哈希表的工作原理,请存储一个自定义对象到HashSet中。
1 packagecn.sxt03.hashset;2
3
4
5 public classStudent {6
7 privateString id;8
9 privateString name;10
11 private intage;12
13
14
15 //…
16
17
18
19
20
21 @Override22
23 public inthashCode() {24
25 final int prime = 31;26
27 int result = 1;28
29 result = prime * result +age;30
31 result = prime * result + ((id == null) ? 0: id.hashCode());32
33 result = prime * result + ((name == null) ? 0: name.hashCode());34
35 returnresult;36
37 }38
39
40
41 @Override42
43 public booleanequals(Object obj) {44
45 if (this ==obj)46
47 return true;48
49 if (obj == null)50
51 return false;52
53 if (getClass() !=obj.getClass())54
55 return false;56
57 Student other =(Student) obj;58
59 if (age !=other.age)60
61 return false;62
63 if (id == null) {64
65 if (other.id != null)66
67 return false;68
69 } else if (!id.equals(other.id))70
71 return false;72
73 if (name == null) {74
75 if (other.name != null)76
77 return false;78
79 } else if (!name.equals(other.name))80
81 return false;82
83 return true;84
85 }86
87
88
89 @Override90
91 publicString toString() {92
93 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";94
95 }96
97
98
99 }
总结
[1]如果向HashSet中存储元素时,元素一定要实现hashCode方法和equals方法。
[2] 优点:添加、删除、查询效率高;缺点:无序
3.3 LinkedHashSet
LinkedHashSet是Set接口的实现类,底层数据结构哈希表+链表
哈希表用于散列元素;链表用于维持添加顺序。
如果要添加自定义对象元素,也需要重写hashCode和equals方法。
3.4 TreeSet
TreeSet 是Set接口的实现类,底层数据结构是二叉树。
TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现出自然顺序。
3.4.1 TreeSet工作原理
添加一个新元素t的存储的步骤:
[1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;
[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤
[3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤
输出时按照一定的规则:左子树->根节点->右子树
根据TreeSet的工作原理,向TreeSet添加自定义元素?
向TreeSet中添加元素时,一定要提供比较策略,否则会出现ClassCastException。
比较策略分两种:内部比较器和外部比较器
3.4.2 内部比较器
当一个自定义对象实现Comparable并实现compareTo方法时,通过指定具体的比较策略,此时称为内部比较器。
1 packagecn.sxt05.treeset;2
3
4
5 public class Student implements Comparable{6
7 privateString id;8
9 privateString name;10
11 private intage;12
13
14
15 //。。。
16
17
18
19 @Override20
21 publicString toString() {22
23 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";24
25 }26
27
28
29 @Override30
31 public intcompareTo(Student o) {32
33 if(this.getAge()
35 return -1;36
37 }else if(this.getAge() ==o.getAge()) {38
39 return 0;40
41 }else{42
43 return 1;44
45 }46
47 }48
49
50
51 }
比较策略的几种情况
[1]比较策略一般当前对象写在前面,待比较对象也在后面,比较结果默认升序
return this.getAge() - o.getAge() ;
如果想要降序,改变两个比较对象的位置即可。
[2] 多种比较因素
1 @Override2
3 public intcompareTo(Student o) {4
5 /*if(this.getAge()
7 return -1;8
9 }else if(this.getAge() == o.getAge()) {10
11 return 0;12
13 }else {14
15 return 1;16
17 }*/
18
19
20
21 //return this.getAge() - o.getAge() ;
22
23
24 if(this.getAge()
26 return -1;27
28 }else if(this.getAge() ==o.getAge()) {29
30 return this.getName().compareTo(o.getName());31
32 }else{33
34 return 1;35
36 }37
38 }
3.4.3 外部比较器
当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。
Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。
TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator
接口。
需求:按照字符串的长度比较
1 public classTest01 {2
3 public static voidmain(String[] args) {4
5
6 LenComparator lenComparator = newLenComparator();7
8 TreeSet set2 = new TreeSet(lenComparator);9
10
11
12 set2.add("banana");13
14 set2.add("coco");15
16 set2.add("apple");17
18 set2.add("apple");19
20 System.out.println(set2);21
22
23
24 }25
26 }27
28
29 class LenComparator implements Comparator{30
31
32
33 @Override34
35 public intcompare(String o1, String o2) {36
37 return o1.length() -o2.length();38
39 }40
41 }
使用匿名内部类优化
1 public classTest02 {2
3 public static voidmain(String[] args) {4
5
6 TreeSet set2 = new TreeSet(new Comparator() {7
8
9 @Override10
11 public intcompare(String o1, String o2) {12
13 return o1.length() -o2.length();14
15 }16
17
18 });19
20 set2.add("banana");21
22 set2.add("coco");23
24 set2.add("apple");25
26
27 set2.add("apple");28
29 System.out.println(set2);30
31
32 }33
34 }
3.5 Map接口
Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。
Map 容器接口中提供了增、删、改、查的方式对集合进行操作。
Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。
3.5.1 map常用方法
1 public static voidmain(String[] args) {2
3
4
5 /**
6
7 * 增:put/putAll8
9 * 删:clear/remove10
11 * 改:put12
13 * 查:get/containsKey/containsValue14
15 * 其他:isEmpty/size16
17 */
18
19
20
21 Map map = new HashMap();22
23
24
25 //【1】put
26
27 map.put("A", "apple");28
29 map.put("B", "banana");30
31 map.put("C", "coco");32
33
34
35 //【2】删除36
37 //map.clear();38
39 //map.remove("A");40
41
42
43 //【3】修改44
45 //map.put("A", "apple x");46
47
48
49 //【4】查看
50
51 String val = map.get("A");52
53 System.out.println(map.containsKey("D"));54
55
56
57
58
59 System.out.println(map);60
61 }
3.5.2 map接口的遍历
通过keySet() 返回map中键的set集合。
1 public static voidmain(String[] args) {2
3
4
5 Map map = new HashMap();6
7
8
9 map.put("B", "banana");10
11 map.put("A", "apple");12
13 map.put("C", "coco");14
15 //map无序16
17 //可以根据key的自然顺序 让map有序 => 一般用string作为key
18
19 System.out.println(map);20
21
22
23
24
25 //遍历
26
27 Set keys =map.keySet();28
29 for(String key : keys) {30
31 System.out.println(key+"=>"+map.get(key));32
33 }34
35
36 Iterator it =keys.iterator();37
38 while(it.hasNext()) {39
40 String key =it.next();41
42 System.out.println(key+"=>"+map.get(key));43
44 }45
46 }
map中以键值对作为元素,键值对在map中称为entry,entrySet返回键值对的set集合。
1 public static voidmain(String[] args) {2
3
4
5 Map map = new HashMap();6
7
8
9 map.put("B", "banana");10
11 map.put("A", "apple");12
13 map.put("C", "coco");14
15 //map无序16
17 //可以根据key的自然顺序 让map有序 => 一般用string作为key
18
19 System.out.println(map);20
21
22 //entrySet
23
24 Set> entrySet =map.entrySet();25
26 for (Entryentry : entrySet) {27
28 System.out.println(entry.getKey()+"=>"+entry.getValue());29
30 }31
32
33 Iterator> it2 =entrySet.iterator();34
35 while(it2.hasNext()) {36
37 Entry entry =it2.next();38
39 System.out.println(entry.getKey()+"=>"+entry.getValue());40
41 }42
43 }
Map接口的实现类HashMap、LinkedHashMap、TreeMap
3.6 HashMap
HashMap 是Map的实现类,key以HashSet存储。
1 public static voidmain(String[] args) {2
3
4
5 /*
6
7 HashMap map = new HashMap();8
9
10
11 ArrayList list1 = new ArrayList();12
13 list1.add("alex");14
15 list1.add("alice");16
17 list1.add("allen");18
19 map.put("A", list1);20
21
22
23
24
25 ArrayList list2 = new ArrayList();26
27 list2.add("ben");28
29 list2.add("bill");30
31 map.put("B", list2);32
33
34
35 System.out.println(map);36
37 */
38
39
40
41
42
43 HashMap map = new HashMap();44
45
46
47 ArrayList list1 = new ArrayList();48
49 list1.add("alex");50
51 list1.add("alice");52
53 list1.add("allen");54
55 Student s1 = new Student("001", "大狗", 20);56
57 map.put(s1, list1);58
59
60
61 ArrayList list2 = new ArrayList();62
63 list2.add("ben");64
65 list2.add("bill");66
67 Student s2 = new Student("001", "大狗", 20);68
69 //修改
70
71 map.put(s2, list2);72
73 System.out.println(map);74
75
76
77 }
总结:
[1] 向HashMap中存储元素时,key一定要实现hashCode和equals(用于去重,用以符合哈希表工作原理)
[2] 一般建议使用String作为Map接口的key
3.7 LinkedHashMap
LinkedHashMap是Map接口的实现类,key以LinkedHashSet存储。
哈希表散列key,链表维持key的添加顺序。
1 public static voidmain(String[] args) {2
3 /*LinkedHashMap map = new LinkedHashMap();4
5 ArrayList list2 = new ArrayList();6
7 list2.add("ben");8
9 list2.add("bill");10
11 map.put("B", list2);12
13
14
15 ArrayList list1 = new ArrayList();16
17 list1.add("alex");18
19 list1.add("alice");20
21 list1.add("allen");22
23 map.put("A", list1);24
25
26
27 System.out.println(map);*/
28
29
30 HashMap map = new HashMap();31
32 ArrayList list1 = new ArrayList();33
34 list1.add("alex");35
36 list1.add("alice");37
38 list1.add("allen");39
40 Student s1 = new Student("001", "大狗", 20);41
42 map.put(s1, list1);43
44
45
46 ArrayList list2 = new ArrayList();47
48 list2.add("ben");49
50 list2.add("bill");51
52 Student s2 = new Student("001", "大狗", 20);53
54 //修改
55
56 map.put(s2, list2);57
58 System.out.println(map);59
60
61
62 }
1.8 TreeMap
TreeMap是Map的实现类,key以TreeSet存储。
1 public static voidmain(String[] args) {2
3
4
5
6
7 /*TreeMap map = new TreeMap(new Comparator() {8
9
10
11 @Override12
13 public int compare(String o1, String o2) {14
15 return o1.length() - o2.length();16
17 }18
19 });20
21
22
23 ArrayList list2 = new ArrayList();24
25 list2.add("ben");26
27 list2.add("bill");28
29 map.put("Aa", list2);30
31
32
33 ArrayList list1 = new ArrayList();34
35 list1.add("alex");36
37 list1.add("alice");38
39 list1.add("allen");40
41 map.put("B", list1);42
43
44
45 System.out.println(map);*/
46
47
48
49
50
51
52
53 TreeMap map = new TreeMap(new Comparator() {54
55
56
57 @Override58
59 public intcompare(Student o1, Student o2) {60
61 return o1.getAge() -o2.getAge();62
63 }64
65 });66
67
68
69 ArrayList list1 = new ArrayList();70
71 list1.add("alex");72
73 list1.add("alice");74
75 list1.add("allen");76
77 Student s1 = new Student("001", "大狗", 20);78
79 map.put(s1, list1);80
81
82
83 ArrayList list2 = new ArrayList();84
85 list2.add("ben");86
87 list2.add("bill");88
89 Student s2 = new Student("001", "2狗", 20);90
91 //修改
92
93 map.put(s2, list2);94
95 System.out.println(map);96
97
98
99 }
1.9 总结