# 集合框架
[TOC]
## 什么是集合
Java中的集合是工具类,可以存储任意数量的具有共同属性的对象。
>[info] 集合类存放于java.util包中。
> 集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用
>[success] 在集合框架中,主要分为 Collection 和 Map 两大接口。
> 在 Collection 中又分为 List (有序集合) 和 Set (无序集合)。List 和 Set 都是接口。
> 其中Collection存储的是元素,Map存储的key-value键值对。
>[warning] 集合框架存储的元素可以是不定长的,即可以任意的添加,但是数组在定义的时候就确定了长度。实际开发中,对于同类型数据的结构,一般使用 Collection 结构会较多。
## Collection
![](https://img.kancloud.cn/57/5a/575a8b4a5f479df91165f236ea99381b_1004x562.png)
在Collection中,根据不同的数据结构是使用方法,分为Set(无序的数据集合,元素不可重复)、Queue(队列)、List(有序的集合,元素可以重复)。
在Collection中的定义中Interface Collection,是一种泛型结构,意思是在使用Collection定义对象的时候,需要指定存储的元素数据类型(强调:**在集合中存储的数据元素必须都是引用数据类型**)。
### List
list中的内容是有序的并且可以重复的,我们也称之为序列;
list可以精确的控制每个元素的插入位置,或者删除某个位置的元素;
>[info] 是实际开发中用的最多的一种数据结构,存储的单个元素,使用**泛型**去强制约束 List 中存放的是一致的数据类型
> 在List接口中,最常用的实现类为ArrayList和LinkedList,其中ArrayList是运用最多的。
**语法**
~~~
List<E> list = new ArrayList<E>();
~~~
**插入元素**
add()
**遍历元素**
* 通过元素索引下标方式 for 循环
* 通过 foreach 循环
* 通过迭代器 Iterator
**删除元素**
如果通过遍历去查找相关元素进行删除的时候,不要使用 list.remove(int index) 该方法,因为使用该方法,会动态的直接改变集合的元素结构,导致遍历的不完整或者有错误。要使用迭代器遍历集合,调用 Iterator.remove() 方法删除。
### Set
不详细阐述,在遍历的时候不能使用索引方式,只能通过迭代器和 foreach。
## Map
![](https://img.kancloud.cn/e1/bd/e1bd5e2144e1efcd3111df395aea5eb5_954x491.png)
类似的可以理解给集合元素中的值定义了一个 Key 键(遍历),之后可以通过相关的方法快速的定位到具体的 Value 中。
Map中存储是key-value键值对,在Map接口中,我们主要使用的实现类为HashMap。
在使用HashMap类的时候,插入的顺序和最后遍历出来的顺序可以是有差异的,因为本身HashMap结构它是无序的。
通过map.put(key, value)方法进去数据的写入,同样的要注意使用泛型。(强调:**Map中的key键和value值的数据元素必须都是引用数据类型**)。
* * *
**语法**
~~~
Map<k,v> map= new HashMap<k,v>();
~~~
Map集合中的一些注意点:
* key必须是唯一的,不唯一,那么后面的value会把前面的value覆盖
* 对于HashMap,key可以为空,value可以为空,也可以不为空
* HashTable的key和value不能为空
* properties的key和value必须为String类型的
**获取某个 key 的 value**
Value get(Key)
**如何遍历 Map 结构**
获取 Map 的 Key 集合,通过遍历 Key 集合,获取 Value 值。
1. 获取 key 集合:map.keySet();
2. 遍历 Key 集合:iterator;
3. 获取 Value 值:get(key);
## 开发注意事项
在实际开发中,List 一般使用 ArrayList 实现类去构建,Map 一般使用 HashMap 实现类去构建。
要掌握对于 List 和 Map 的添加元素、遍历元素。
要认识集合框架中关于对象在内存中的存储方法。
## 本节课的代码片段
**代码运行内存图**
![](https://img.kancloud.cn/b1/45/b14565f9fea59d7132b628f762dcf8d1_1979x849.png)
Clazz.java
~~~
package com.ntqingniao.j96.bean;
import java.util.List;
public class Clazz {
private String name;
private String code;
private List<Student> students;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
~~~
Clazz2.java
~~~
package com.ntqingniao.j96.bean;
import java.util.Map;
public class Clazz2 {
private String name;
private String code;
private Map<String, Student> stus;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Map<String, Student> getStus() {
return stus;
}
public void setStus(Map<String, Student> stus) {
this.stus = stus;
}
}
~~~
Client.java
~~~
package com.ntqingniao.j96.bean;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Client {
public static void main(String[] args) {
Student pxj = new Student("彭贤君", "001");
Student hjn = new Student("黄佳男", "002");
Clazz j96 = new Clazz();
j96.setName("Java96班");
j96.setCode("java96");
// Step1:学生类型的集合定义完成了
List<Student> stus = new ArrayList<Student>();
// Step2: 添加数据
stus.add(pxj);
stus.add(hjn);
// Step3: 追加一个新的学生
Student ljn = new Student("陆佳楠", "003");
stus.add(ljn);
// Step4: 设置班级学生属性
j96.setStudents(stus);
// for (int i = 0; i < j96.getStudents().size(); i++) {
// Student stu = j96.getStudents().get(i);
// if (stu.getName().equals("黄佳男")) {
// stu.setCode("004");
// }
// }
// for (int i = 0; i < j96.getStudents().size(); i++) {
// // 打印对象,如果没有显式的调用toString()方法,编译器也会执行toString();
// System.out.println(j96.getStudents().get(i));
// }
//
// for (int i = 0; i < stus.size(); i++) {
// System.out.println(stus.get(i));
// }
//
// for (Student stu : stus) {
// System.out.println(stu);
// }
//
// for (Student stu : stus) {
// if (stu.getName().equals("黄佳男")) {
// stu.setCode("005");
// }
// }
// for (int i = 0; i < j96.getStudents().size(); i++) {
// Student stu = j96.getStudents().get(i);
// System.out.println(stu.getName());
// if (stu.getName().equals("彭贤君")) {
// j96.getStudents().remove(i); // 这样的实现是有问题的
// System.out.println(j96.getStudents().size());
// }
// }
//
// for (Student stu : stus) {
// System.out.println(stu);
// }
// 使用迭代器遍历
// Step1:创建迭代器
Iterator<Student> it = stus.iterator();
while (it.hasNext()) {
Student stu = it.next();
System.out.println(stu);
if (stu.getName().equals("黄佳男")) {
it.remove();
}
}
System.out.println("处理完的结果======================");
it = stus.iterator();
while (it.hasNext()) {
Student stu = it.next();
System.out.println(stu);
}
}
}
~~~
Client2.java
~~~
package com.ntqingniao.j96.bean;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Client2 {
public static void main(String[] args) {
Student pxj = new Student("彭贤君", "001");
Student hjn = new Student("黄佳男", "002");
Clazz2 j96 = new Clazz2();
j96.setName("Java96班");
j96.setCode("java96");
Map<String, Student> stus = new HashMap<String, Student>();
stus.put("001", pxj);
stus.put("002", hjn);
j96.setStus(stus);
Student stu = stus.get("001");
System.out.println(stu.getName());
System.out.println(stus.containsKey("003"));
// 遍历Map
// 第一步:获取Map中的Key集合
Set<String> keySet = stus.keySet();
// 第二步:迭代Key集合
Iterator<String> keyIt = keySet.iterator();
while (keyIt.hasNext()) {
String key = keyIt.next();
// 根据Key获取Value
Student value = stus.get(key);
System.out.println(key + "=" + value);
}
}
}
~~~
Client3.java
~~~
package com.ntqingniao.j96.bean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Client3 {
public static void main(String[] args) {
Student pxj = new Student("彭贤君", "10", 20);
Student hjn = new Student("黄佳男", "008",19);
Student liuxiaowei = new Student("刘晓卫", "002",22);
Student liuxiaowei2 = new Student("刘晓卫", "005",15);
Student liuxiaowei3 = new Student("刘晓卫", "001",25);
Student liuxiaowei4 = new Student("刘晓卫", "004",13);
List<Student> stus = new ArrayList<Student>();
stus.add(pxj);
stus.add(hjn);
stus.add(liuxiaowei);
stus.add(liuxiaowei2);
stus.add(liuxiaowei3);
stus.add(liuxiaowei4);
Collections.sort(stus);
for(Student stu : stus) {
System.out.println(stu);
}
}
}
~~~
Student.java
~~~
package com.ntqingniao.j96.bean;
public class Student implements Comparable<Student>{
private String name;
private String code;
private int age;
public Student(String name, String code) {
super();
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, String code, int age) {
super();
this.name = name;
this.code = code;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", code=" + code + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
if (this.age > o.age) {
return 1;
} else if (this.age == o.age) {
return 0;
} else {
return -1;
}
}
}
~~~
**扑克牌实例程序**
>[danger] 由于出现花色特殊的字符,需要把Java文件的字符编码定义为 UTF-8
Constants.java
~~~
package com.ntqingniao.j96.bean;
public class Constants {
public static String[] FOLLOWS = {"♠","♥","♣","♦"};
public static int[] NUMBERS = {2,3,4,5,6,7,8,9,10,11,12,13,14};
public static String[] NUMBERS_STR = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
}
~~~
Poker.java
~~~
package com.ntqingniao.j96.bean;
public class Poker {
private String follow;
private int number;
public int compare(Poker p1, Poker p2) {
return 0;
}
public Poker(String follow, int number) {
super();
this.follow = follow;
this.number = number;
}
public String getFollow() {
return follow;
}
public void setFollow(String follow) {
this.follow = follow;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public String toString() {
return this.getFollow() + Constants.NUMBERS_STR[this.getNumber()-2];
}
}
~~~
Client4.java
~~~
package com.ntqingniao.j96.bean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Client4 {
public static void main(String[] args) {
List<Poker> pokers = new ArrayList<Poker>();
for (String follow : Constants.FOLLOWS) {
for (int number : Constants.NUMBERS) {
Poker poker = new Poker(follow, number);
pokers.add(poker);
}
}
int i = 0;
for (Poker poker : pokers) {
System.out.print(poker + " ");
i++;
if (i % 13 == 0) {
System.out.println();
}
}
System.out.println("==========洗牌==========");
for (int j = 0; j < 5; j++) {
System.out.println("===========第" + (j + 1) + "副牌==========");
Collections.shuffle(pokers);
i = 0;
for (Poker poker : pokers) {
System.out.print(poker + " ");
i++;
if (i % 13 == 0) {
System.out.println();
}
}
}
}
}
~~~
## 练习
1. **定义一个方法listTest(ArrayList al, Integer s),要求返回s在al里面第一次出现的索引,如果s没出现过返回-1。**
~~~java
import java.util.ArrayList;
import java.util.List;
public class ListTestDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(7);
list.add(4);
list.add(2);
list.add(1);
list.add(5);
list.add(2);
System.out.println(ListTest(list, 2));
System.out.println(list.indexOf(7));
}
public static int ListTest(List<Integer> al, Integer s) {
for(int i = 0; i < al.size(); i++) {
if(al.get(i).equals(s)) {//此时集合中和s都是引用数据类型。判断是否相等采用的是equals方法
return i;
}
}
return -1;
}
}
~~~
2. **现在有一个map集合如下:**
~~~
Map map = new HashMap();
map.put(1, "张三丰");
map.put(2, "周芷若");
map.put(3, "汪峰");
map.put(4, "灭绝师太");
~~~
**要求:**
1. **遍历集合,并将序号与对应人名打印。**
2. **向该map集合中插入一个编码为5姓名为李晓红的信息**
3. **移除该map中的编号为1的信息**
4. **将map集合中编号为2的姓名信息修改为"周林"**
~~~java
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapStudy {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1,"张三丰");
map.put(2,"周芷若");
map.put(3,"汪峰");
map.put(4,"灭绝师太");
//新增
map.put(5, "李晓红");
//删除
map.remove(1);
//修改(覆盖)
map.put(2, "周林");
//遍历
Set<Integer> set = map.keySet();
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
Integer key = it.next();
System.out.println("序号为:" + key + ",姓名为:" + map.get(key));
}
}
}
~~~
3. **有2个数组,第一个数组内容为:\[黑龙江省,浙江省,江西省,广东省,福建省\],第二个数组为:\[哈尔滨,杭州,南昌,广州,福州\],将第一个数组元素作为key,第二个数组元素作为value存储到Map集合中。如{黑龙江省=哈尔滨, 浙江省=杭州, …}。**
~~~java
import java.util.HashMap;
import java.util.Map;
public class MapStudy {
public static void main(String[] args) {
String[] province = {"黑龙江省","浙江省","江西省","广东省","福建省"};
String[] city = {"哈尔滨","杭州","南昌","广州","福州"};
Map<String,String> map = new HashMap<String,String>();
for(int i = 0; i < province.length; i++) {
map.put(province[i], city[i]);
}
System.out.println(map);
}
}
~~~
4. **双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1—33中选择;蓝色球号码从1—16中选择;请随机生成一注双色球号码。(要求同色号码不重复)**