十二、集合进阶
1、Collection
1、集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
2、集合类体系
3、Collection集合概述和使用
// 创建Collection集合的对象
Collection<String> c = new ArrayList<String>();
// 添加元素:boolean add(E e)
c.add("hello");
c.add("java");
System.out.println(c);
4、Collection集合常用方法
boolean add(E e):添加元素
boolean remove(Object o):从集合中移除指定的元素
void clear():清空集合中的元素
boolean contains(Object o):判断集合中是否存在指定的元素
boolean isEmpty():判断集合是否为空
int size():集合的长度,也就是集合中元素的个数
5、迭代器
Iterator:集合的专用遍历方式 是一个接口
// c是一个集合对象
Iterator<String> it = c.iterator();
System.out.println(it.next()); # 返回迭代中的下一个元素
6、集合使用步骤
2、List
1、有序集合(序列)
有序:存储和取出的元素顺序一致
可重复:存储的元素可重复
2、特有方法
3、并发修改异常
ConcurrentModificationException
产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成迭代器获取元素中判断预期修改值和实际修改值不一致
解决方法:用for循环遍历,然后用集合对象做对应的操作即可
4、列表迭代器 ListIterator
通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历列表迭代器,在迭代器期间修改列表,并获取列表中迭代器的当前位置
5、增强for循环
增强for:简化数组和Collection集合的遍历
- 实现Iterable接口和Collection集合的遍历
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
案例:三种遍历方式
// 迭代器
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+","+s.getAge());
}
// 普通for:带有索引的遍历方式
for(int i=0; i<list.size(); i++){
Student s = list.get(i);
System.out.println(s.getName()+","+s.getAge());
}
// 增强for,最方便的遍历方式
for(Student s:list){
System.out.println(s.getName()+","+s.getAge());
}
6、数据结构
- 栈
- 队列
- 数组(增删慢,查询快)
- 链表(增删快,查询慢)
7、List
List集合常用子类:ArrayList、LinkedList
ArrayList:底层数据结构是数组
LinkedList:底层数据结构是链表
LinkedList集合的特有功能
3、Set
1、Set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,索引不能使用普通for循环遍历
2、哈希值
哈希值是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
- public int hashCode():返回对象的哈希码值
对象的哈希值特点:
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不相同的;通过方法重写,可以实现不同对象的哈希值是相同的
3、HashSet集合概述和特点
集合特点:
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,索引不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
// 创建集合对象
HashSet<String> hs = new HashSet<String>();
// 添加元素
hs.add("hello");
hs.add("java");
hs.add("hello"); # 重复了,不输出
// 遍历
for(String s : hs){
System.out.println(s);
}
// 输出端
hello
java
4、HashSet集合证元素唯一性
存入的元素和以前的元素进行比较哈希值
相同——>继续向下执行,把元素添加到集合
不同——>会调用对象的equals()方法比较
返回false——>继续向下执行,把元素添加到集合
返回True——>元素重复,不存储
要保证元素唯一性,需要重写hasCode()和equals()
5、LinkedHashSet集合概述和特点
集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
6、TreeSet集合概述和特点
7、自然排序Comparable的使用
8、比较器排序Comparator的使用
4、泛型
1.概述
定义
public class Generic<T>{
private T t;
public T getT(){
return t;
}
public void setT(){
this.t = T;
}
}
使用
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(30);
Generic<Boolean> g3 = new Genertic<Boolean>();
g3.setT(true);
Generic<String> g3 = new Genertic<String>();
g3.setT("林青霞");
3.泛型方法改进
定义
public class Generic{
public <T> void show(T t){
System.out.println(t);
}
}
使用
Generic g = new Generic();
g.show("林青霞");
g.show(30);
g.show(true);
4.接口
定义
public class GenericImp<T> implements Generic<T>{
@override
public void show(T t){
System.out.println(t);
}
}
5.类型通配符
6.可变参数
方法参数个数是可变的
public class ArgsDemo{
public static void(String[] args){
System.out.println(sum(10, 20, 30));
System.out.println(sum(10, 20, 30, 40, 50, 60, 70));
}
// 这里的可变参数是数组
public static int sum(int... a){
int sum = 0;
for(int i:a){
sum += i;
}
return sum;
}
}
7、可变参数的使用(三个方法)
5、Map
import java.util.Map;
1、概述
// 创建集合对象
Map<String,String> map = new HashMa<String, String>();
// 将指定的值与该映射中的指定键相关联 put(key, value)
map.put("it001", "林青霞");
map.put("it002", "张曼玉");
map.put("it003", "王祖贤");
map.put("it003", "王祖蓝");
// 输出
System.out.pirntln(map);
{it003=王祖蓝,it001=林青霞,it002=张曼玉}
2、map集合基本功能
3.map集合的获取功能
// 遍历
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> me : entrySet){
String key = me.getKey();
String value = me.getValue();
System.out.println(key+","+value);
}
4、案例:HashMap集合存储学生对象并遍历
5、集合嵌套之ArrayList嵌套HashMap
public class ArrayListIncludeHashMapDemo{
public static void main(String[] args){
// 1.创建ArrayList集合
ArrayList<HashMap<String,String>>array = new ArrayList<HashMap<String,String>>();
// 2.创建HashMap集合,并添加键值对元素
HashMap<String, String>hm1 = new HashMap<String, String>();
hm1.put("孙策","大乔");
hm1.put("周瑜","小乔");
// 3.把HashMap作为元素添加到ArrayList集合
array.add(hm1);
HashMap<String, String>hm2 = new HashMap<String, String>();
hm2.put("郭靖","黄蓉");
hm2.put("杨过","小龙女");
array.add(hm2);
// 4.遍历ArrayList集合
for(HashMap<String,String>hm:array){
Set<String> keySet = hm.keySet();
for(String key:keySet){
String value = hm.get(key);
System.out.println(key+","+value);
}
}
}
}
6、集合嵌套之HashMap嵌套ArrayList
7、案例——统计字符出现的个数
6、Collections
1、概述
是针对集合操作的工具类
2、Collections常用的方法
sort reverse shuffle
3、案例:模拟斗地主
需求:通过程序实现斗地主过程中的洗牌,发牌和看牌;要求:对牌进行排序
public class PokerDemo{
public static void main(String[] args){
//1. 创建HashMap,键是编号,值是牌
HashMap<Integer, String> hm = new HashMap<Integer, String>();
// 2.创建ArrayList,存储编号
ArrayList<Integer> array = new ArrayList<Integer>();
// 3.创建花色数组和点数数组
String colors = {"♦","♠","♥","♣"};
String numbers = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
// 4.从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号
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);
// 5.洗牌(洗的是编号),用collections的shutffle()方法实现
Collections.shuffle(array);
// 6.发牌(发的也是编号,为了保证编号是排序的,创建TreeSet集合接收
TreeSet<Integer> Set1 = new TreeSet<Integer>();
TreeSet<Integer> Set2 = new TreeSet<Integer>();
TreeSet<Integer> Set3 = new TreeSet<Integer>();
TreeSet<Integer> dpSet = new TreeSet<Integer>();
for(int i = 0; i < array.size(); i++){
int x = array.get(i);
if(i >= array.size() - 3){
dpSet.add(x);
}else if (i % 3 == 0){
Set1.add(x);
}else if (i % 3 == 1){
Set2.add(x);
}else if (i % 3 == 2){
Set3.add(x);
}
}
// 8.调用看牌方法
lookPoker("林青霞", Set1, hm);
lookPoker("刘洋", Set2, hm);
lookPoker("风清扬", Set3, hm);
lookPoker("底牌", dpSet, hm);
}
// 7.定义方法看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm){
System.out.print(name + "的牌是:");
for(Integer key : ts){
String poker = hm.get(key);
System.out.print(poker+"");
}
System.out.println();
}
}