- 集合知识回顾
- 1. Collection
- 2. List
- 3. Set
- 4. 泛型
- 5. Map
- 6. Collections
- 7. 案例
集合知识回顾
集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
集合体系结构:
1.1 Collection集合常用方法
| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 添加元素 |
| boolean remove(Object o) | 从集合中移除指定元素 |
| void clear() | 清空集合中元素 |
| boolean contains(Object o) | 判断集合中是否存在指定的元素 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中元素的个数 |
1.2 Collection集合的遍历
Iterator:迭代器,集合的专用遍历
- Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的所以我们说它是依赖于集合存在的
Iterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
//迭代器方式 Iteratorit = c.iterator(); //多态的方式创建对象 //E.next():返回迭代中的下一个元素 //用while循环改进判断 while (it.hasNext()){ String s= it.next(); System.out.println(s); }
2. List
2.1 List集合概述
List集合概述
- 有序集合(也称为序列)。该界面的用户可以精确控制列表中的每个元素的插入位置。用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复元素
List集合特点
- 有序:存储和取出的顺序一致
- 可重复:存储的元素可以重复
2.2 List集合特有方法
| 方法名 | 说明 |
|---|---|
| void add(int index,E element) | 在集合中指定位置插入指定元素 |
| E remove(int index) | 删除指定索引处元素,返回被删除的元素 |
| E set(int index,E element) | 修改指定索引处元素,返回被修改的元素 |
| E get(int index) | 返回指定索引处的元素 |
2.3 for循环遍历
//遍历集合
//用for循环改进遍历
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
2.4 并发修改异常
(modCount和exceptionmodCount的问题)
并发修改异常: ConcurrentModification
产生原因: 迭代器遍历的过程中,通过集合对象修改了集合中的元素长度造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案: 用for循环遍历,然后用集合对象做对应的操作即可
2.5 ListIterator
ListIerator:列表迭代器
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListIterator中的常用方法
| 方法名 | 说明 |
|---|---|
| E next() | 返回迭代中的下一个元素 |
| boolean hasNext() | 如果迭代具有更多元素,则返回true |
| E previous() | 返回列表中的上一个元素 |
| boolean hasPrevious | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true |
| void add(E e) | 将指定的元素扎入列表 |
2.6 增强for循环
增强for:简化数组和Collection集合遍历
- 实现Iterator接口的类允许其对象成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个iterator迭代器
增强for的格式
- 格式:
for(元素数据类型 变量名:数组或者Collection集合){
//此处使用变量即可
}
2.7 List集合子集特点
List集合常用子类:ArrayList,LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
2.8 LinkedList集合的特有功能
| 方法名 | 说明 |
|---|---|
| public void addFirst(E,e) | 在该列表开头插入指定的元素 |
| public void addLast(E,e) | 将指定的元素添加到此列表的末尾 |
| public E getFiret() | 返回此列表中的第一个元素 |
| public E getLast() | 返回此列表中的最后一个元素 |
| public E removeFirst() | 从列表中删除并返回第一个元素 |
| public E removeLast() | 从列表中删除并返回最后一个元素 |
3. Set
3.1 Set集合概述和特点
Set集合特点
- 不包含重复元素的集合
- 没有带索引方法,所以不能直接使用for循环遍历
3.2 哈希值
哈希值:是JKD根据对象的 地址 或者 字符串 或者 数字 算出来的int类型的数值
Object类中有一个方法可以获取对象哈希值
- public int hasCode():返回对象的哈希码值
对象的哈希值特点
- 同一个对象多次调用hasCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写hasCode()方法,可以实现让不同的对象哈希值相同
3.3 HashSet集合概述和特点
HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
3.4 HashSet集合保证元素唯一性源码分析
HashSet集合添加一个元素的过程:
HashSet集合存储元素:
- 要保证元素唯一性,需要重写hashCode()和equals()
3.5 常见数据结构之哈希表
哈希表
- JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
- JDK8之后,在长度比较长的时候,底层实现了优化
3.6 LinkedHashSet集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的储存和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复元素
3.7 TreeSet集合概述和特点
TreeSet集合特点
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序 - 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含啊重复元素的集合
3.8自然排序Comparable的使用
结论
- 用TreeSet集合存储自定义对象,无参构造方法使用的是 自然排序 对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
- 重写方法时,一定要注意排序规则必须按照需求的主要条件和次要条件来写
//Student类重写compareTo()方法
public int compareTo(Student s){
//return 0; 不存
//return 1; 顺着存
//return -1; 倒着存
//按年龄从小到大排序
int num=this.age-s.age;
//按年龄从大到小排序
//int num=s.age-this.age;
//年龄相同时,按照姓名的字母顺序排序
int num2 = num==0?this.name.compareTo(s.name):num;
return num2;
}
3.9 比较器排序Comparator的使用
public class TreeSet02 {
public static void main(String[] args) {
TreeSet ts=new TreeSet(new Comparator() { //创建内部类,底下自动生成
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge(); //不能直接访问age,因为是Student类中的私有变量,所以用getAge()方法
int num2 = num==0? s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
结论
- 用TreeSet集合存储自定义对象,带参构造方法使用的是 比较器排序 对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
- 重写方法时,一定要注意排序规则,必须按照要求的主要条件和次要条件来写
4. 泛型
4.1 泛型概述
本质是参数化类型,就是操作的数据类型被指定为一个参数
(将来具体调用时候给定的类型可以看成实参,并且实参的类型只能是“引用数据类型”)
(泛型是为了灵活的取值和赋值
泛型的好处
- 把运行时的问题提前到了编译期
- 避免了强制类型转换
4.2 通过泛型引申出泛型类,泛型方法,泛型接口
4.3 类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
- 类型通配符: >
- List> : 表示元素类型未知的List,他的元素可以匹配 任何的类型
- 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
- 类型通配符上限:
- List:它表示的类型是Number或者子类型
除了可以指定类型通配符的上限,也可以指定类型通配符的下限
- 类型通配符下限:
- List: 他表示的类型是Number或者其父类型
4.4 可变参数
可变参数又称为参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
- 格式:修饰符 返回值类型 方法名(数据类型…变量名){ }
- 范例:
public class Demo1 {
public static void main(String[] args) {
System.out.println(sum(10,11,12));
System.out.println(sum(10,11,12,13));
System.out.println(sum(10,11,12,13,14));
}
public static int sum(int...a){
int sum = 0;
for(int i:a){
sum += i;
}
return sum;
}
}
可变参数注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
4.5 可变参数的使用
Arrays工具类中有一个静态方法:
- public static List asList(T…a): 返回指定数组支持的固定大小的列表
- 返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
- public static List of(E…elements): 返回包含任意数量元素的不可变列表
- 返回的集合不能做增删操作改
Set接口中有一个静态方法:
- public static Set of(E…elements): 返回一个包含任意数量元素的不可变集合
- 在给元素的时候,不能给重复元素
- 返回的集合不能做增删操作,没有修改方法
5. Map
5.1 Map集合概述和使用
Map集合概述
- Interface Map
K:键的类型 ;V:值的类型 - 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
- 例:学生的学号和姓名
创建Map集合对象
- 多态的方式
- 具体的实现类HashMap
Mapmap = new HashMap (); //V put (K key,V value) 将指定的值与该映射中的指定键关联 map.put("01","aaa"); map.put("02","bbb"); map.put("03","ccc"); System.out.println(map);
5.2 Map集合的基本功能
| 方法名 | 说明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有的键值对元素 |
| boolean containsKey(Object key) | 判断集合是否包含指定的键 |
| boolean containsValue(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
5.3 Map集合的获取功能
| 方法名 | 说明 |
|---|---|
| V get(Object key) | 根据键获取值 |
| Set keySet() | 获取所有键的集合 |
| Collection values() | 获取所有值的集合 |
| Set | 获取所有键值对对象的集合 |
5.4 Map集合的遍历(方式一)
Map集合存储的元素都是成对出现的,所以可以把Map看成是一个夫妻对的集合
遍历思路
- 我们可以把所有的丈夫集中起来 == 获取所有键的集合,用keySet()方法实现
- 遍历丈夫的集合,获取到每一个丈夫 == 遍历键的集合,获取到每一个键,用增强for实现
- 根据丈夫去找对应的妻子 == 根据键去找值,用get(Object key)方法实现
public static void main(String[] args) {
Map map = new HashMap();
map.put("AA","aa");
map.put("BB","bb");
map.put("CC","cc");
// 获取所有键的集合,用keySet()方法实现
Set keySet = map.keySet();
// 遍历键的集合,获取到每一个键,用增强for实现
for (String key: keySet){
// 根据键去找值,用get(Object key)方法实现
String value = map.get(key);
System.out.println(key + "," + value);
}
}
5. 5 Map集合的遍历(方式二)
遍历思路
- 获取所有键值对对象的集合:
Set> entrySet() - 遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry - 根据键值对对象获取键和值
用getKey()得到键
用getValue()得到值
public static void main(String[] args) {
Map map = new HashMap();
map.put("AA", "aa");
map.put("BB", "bb");
map.put("CC", "cc");
Set> entry = map.entrySet();
for (Map.Entry me: entry){
String key = me.getKey();
String value = me.getValue();
System.out.println(key+","+value);
}
}
6. Collections
6.1 Collections概述和使用
Collections类的概述
- 是针对集合操作的工具类
Colections类的常用方法
| 方法名 | 说明 |
|---|---|
| public static | 将指定的列表按升序排序 |
| public static void reverse(List> list) | 反转指定列表中元素的顺序 |
| public static void shuffle(List> list) | 使用默认的随机源随机排列指定的列表 |
7. 案例
统计每个字符串中每个字符出现的次数
//统计每个字符串中每个字符出现的次数
import com.sun.source.tree.Tree;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class Demo {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//创建HashMap集合,键是Character,值是Integer
// HashMap hm = new HashMap(); //不排序
TreeMap hm = new TreeMap(); //排序
//遍历字符串得到每一个字符
for (int i = 0;i
char key = line.charAt(i);
//拿到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
Integer value = hm.get(key);
if(value==null){
//如果返回值是null,说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
hm.put(key,1);
}else{
//如果返回值不是null,说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
value++;
hm.put(key,value);
}
}
//遍历HashMap集合,得到键和值,按照要求进行拼接
StringBuffer sb = new StringBuffer();
Set keySet = hm.keySet();
for(Character key : keySet){
Integer value = hm.get(key);
sb.append(key).append("(").append(value).append(")");
}
String result = sb.toString();
//输出结果
System.out.println(result);
}
}
斗地主
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class DouDemo {
public static void main(String[] args) {
HashMap hm = new HashMap();
ArrayList array = new ArrayList();
String[] colors = {"♦","♣","♥","♠"};
String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
int index = 0;
for (String number:numbers){
for (String color:colors){
hm.put(index,color+number);
array.add(index);
index++;
}
}
hm.put(index,"小王");
array.add(index);
index++;
hm.put(index,"大王");
array.add(index);
Collections.shuffle(array);
TreeSet aaa = new TreeSet();
TreeSet bbb = new TreeSet();
TreeSet ccc = new TreeSet();
TreeSet dp = new TreeSet();
for(int i = 0;i < array.size();i++){
int x = array.get(i);
if(i >= array.size()-3){
dp.add(x);
}else if (i % 3==0){
aaa.add(x);
}else if (i % 3==1){
bbb.add(x);
}else if (i % 3==2){
ccc.add(x);
}
}
lookPoker("爷爷",aaa,hm);
lookPoker("奶娘",bbb,hm);
lookPoker("姑姑",ccc,hm);
lookPoker("底牌",dp,hm);
}
public static void lookPoker(String name,TreeSet ts, HashMap hm){
System.out.println(name+"的牌是:");
for(Integer key:ts){
String poker = hm.get(key);
System.out.println(poker+" ");
}
System.out.println(" ");
}
}



