一、Collection的其他相关知识
1.1 可变参数
是什么:是一种特殊的参数格式,格式:参数类型...参数个数。
本质:是一个数组
特点:可以传入0个或者一个参数、或同时传入多个参数,也可以直接传入一个数组。
好处:灵活的接收数据。
主义事项:一个形参列表只能有一个可变参数;可变参数必须放在参数列表的最后面。
Demo
public static void main(String[] args) {
//调用方法传入的参数的方式
getSum();//不传
getSum(1);//传入一个
getSum(1,23,3,23,22);//传入一个或多个
//getSum(1.2,3);必须传入相同类型的数据
int max = findMax(1, 3,19,32);
System.out.println("最大值:"+max);
}
//定义一个方法,可变参数
//注意事项:1.可变参数只能有一个 2.可变参数放形参列表最后面
public static void getSum(int...a){
}
public static int findMax(int...a){
int max = a[0];
//加强for循环
for (int i : a) {
int max1 = Math.max(max, i);
return max1;
}
return -1;
}
1.2 Collections
是一个操作集合的工具类,其中提供了四种去方法(可以直接类名.方法名去调用)
批量添加元素:
public static <T> boolean addAll(Collection<? super T> c, T... elements)
打乱list集合的元素
public static void shuffle(List<?> list)
对List集合中的元素进行升序排序
public static <T> void sort(List<T> list)
对List集合中元素,按照比较器对象指定的规则进行排序
public static <T> void sort(List<T> list,Comparator<? super T> c)
Demo
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list,"1","22","a","3333","444","ab","445");
System.out.println("批量添加:"+list);
Collections.shuffle(list);
System.out.println("打乱后的:"+list);
Collections.sort(list);
System.out.println("排序后的(默认):"+list);
//lambda表达式
// 方法compareTo()通过对应的ASCII码对应的值判断,第一个一样的判断第二个,以此类推
Collections.sort(list,(o1,o2)->{return o2.compareTo(o1);});
System.out.println("自定义排序规则:"+list);
}
1.3 综合案例(斗地主)
Poker类
public class Poker {
private String point;
private String color;
private int index;
//1. 我们需要定义一个静态的集合,用于存放54张牌
static ArrayList<Poker> pokers = new ArrayList<>();
static {
String[] numbers = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
String[] colors = {"♦", "♣", "♥", "♠"};
int index = 0;
for (String number : numbers) {
for (String color : colors) {
Poker p = new Poker(number,color,index++);
pokers.add(p);
}
}
//添加大小王
Poker xw = new Poker("", "小王", index++);
pokers.add(xw);
Poker dw = new Poker("", "大王", index++);
pokers.add(dw);
//打乱牌
Collections.shuffle(pokers);
}
public Poker() {
}
public Poker(String point, String color, int index) {
this.point = point;
this.color = color;
this.index = index;
}
/**
* 获取
* @return point
*/
public String getPoint() {
return point;
}
/**
* 设置
* @param point
*/
public void setPoint(String point) {
this.point = point;
}
/**
* 获取
* @return color
*/
public String getColor() {
return color;
}
/**
* 设置
* @param color
*/
public void setColor(String color) {
this.color = color;
}
/**
* 获取
* @return index
*/
public int getIndex() {
return index;
}
/**
* 设置
* @param index
*/
public void setIndex(int index) {
this.index = index;
}
public String toString() {
return point+color;
}
}
测试类
public class Demo02 {
/*
1. 我们需要定义一个类,代表牌,包含 点数,花色,定义一个整数记录牌的顺序 index = 0
2. 我们需要准备54张牌,用一个集合存放所有的牌,顺便打乱牌的顺序
3. 创建三个集合,用于存放三个玩家的牌 先遍历前面的51张牌 对i % 3 就可以平均分给三个人了
4. 对每个用户的牌排序
*/
public static void main(String[] args) {
System.out.println("打乱之后的牌:"+Poker.pokers);
//3. 创建三个集合,用于存放三个玩家的牌 先遍历前面的51张牌 对i % 3 就可以平均分给三个人了
ArrayList<Poker> player1 = new ArrayList<>();
ArrayList<Poker> player2 = new ArrayList<>();
ArrayList<Poker> player3 = new ArrayList<>();
ArrayList<Poker> dizhu = new ArrayList<>();
for (int i = 0; i < 51; i++) {
// 获取的到牌数牌里面的每一个
Poker p = Poker.pokers.get(i);
if (i % 3 == 0){
player1.add(p);
}else if (i % 3 == 1){
player2.add(p);
}else {
player3.add(p);
}
}
//底牌
Collections.addAll(dizhu,Poker.pokers.get(51),Poker.pokers.get(52),Poker.pokers.get(53));
// 4. 对每个用户的牌排序
Collections.sort(player1,(o1,o2)->{
return o1.getIndex() - o2.getIndex();
});
Collections.sort(player2,(o1,o2)->{
return o1.getIndex() - o2.getIndex();
});
Collections.sort(player3,(o1,o2)->{
return o1.getIndex() - o2.getIndex();
});
//输出每个玩家的牌
System.out.println("玩家1的牌:"+player1);
System.out.println("玩家2的牌:"+player2);
System.out.println("玩家3的牌:"+player3);
System.out.println("底牌:"+dizhu);
}
}
二、Map集合
2.1 概述
2.1概述
Map集合为双列集合,集合的每个元素“key=value”是一个键值对。Map也叫键值对集合,在Map中键不允许重复,值可以重复,出现相同键不同值的情况下,前面的值会被后面的值覆盖
如:输出的{张三=78,李四=79,王五=100}
2.2 常用方法
public class Demo01 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
//添加元素
map.put("张三",78);
map.put("李四",79);
map.put("王五",90);
System.out.println("添加之后:"+map);
//获取长度
System.out.println("集合的长度为:"+map.size());
//判断是否为空
System.out.println("是否为空:"+map.isEmpty());
//获取对应的键值对
System.out.println(map.get("李四"));
//根据键删除某个值
map.remove("张三");
System.out.println("删除后:"+map);
//包含某个键
System.out.println("包含某个键:"+map.containsKey("李四"));
System.out.println("包含某个值:"+map.containsValue(90));
//获取全部值集合
System.out.println("全部值:"+map.values());
//全部键集合
System.out.println("全部键:"+map.keySet());
//清空集合
map.clear();
System.out.println("清空之后:"+map);
}
}
2.3 遍历方法
分为三种遍历方式:键找值、键值对、lambda
键找值:先把所有的键存入一个集合,再遍历这个集合去找到值
public class Demo01 {
/*
目标:通过键找值 遍历Map集合
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("孙悟空","金箍棒");
map.put("猪八戒","九齿钉耙");
map.put("沙悟净","降妖宝杖");
map.put("唐僧","紧箍咒");
//把键全取出来放到一个集合中
Set<String> keySet = map.keySet();
//遍历这个keySet去获取值
for (String s : keySet) {
String value = map.get(s);
System.out.println(s+"--->"+value);
}
}
}
把“键值对“看成一个整体进行遍历(难度较大)
public class Demo02 {
/*
目标:更够以 ”键值对“ 的方式去遍历集合
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("孙悟空","金箍棒");
map.put("猪八戒","九齿钉耙");
map.put("沙悟净","降妖宝杖");
map.put("唐僧","紧箍咒");
//获取所有“键值对”的集合
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "-->" +value);
}
}
}
lambda:JDK 1.8开始之后的新技术(非常的简单)
public class Demo03 {
/*
目标:lambda遍历Map集合 集合名.forEach 重写其中的 BiConsumer 方法
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("孙悟空","金箍棒");
map.put("猪八戒","九齿钉耙");
map.put("沙悟净","降妖宝杖");
map.put("唐僧","紧箍咒");
//key,value分别对应键、值
map.forEach((key,value)->{
System.out.println(key +"-->"+value);
});
}
}
2.4 HashMap
特点:无序、不重复、无索引
实际上:原来学的Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已。
底层原理:①利用键计算哈希值,寻找位置,判断是否为null,null则存入键,不为null通过equals()方法判断去重。
HashMap如何实现键的唯一性的?
依赖hashCode方法和equals方法保证键的唯一。
如果键要存储的是自定义对象,需要重写hashCode和equals方法。
// HashMap -> 无序 不重复 无索引
Map<String,Integer> map = new HashMap<>();
map.put("张三",22);
map.put("王五",25);
map.put("李四",23);
map.put("张飞",20);
map.put("赵六",28);
map.put("李四",24);
System.out.println(map.size());// 5 是不重复的 要是键一样,值会被后面的覆盖
System.out.println(map);//{李四=23, 张三=22, 张飞=20, 王五=25, 赵六=28}
2.5 LinkedHashMap
特点:有序、不重复、无索引
底层原理:底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。
实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap。
有序指的是存储和取出的顺序。
//LinkedHashMap 有序、不重复、无索引
Map<String,Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("张三",22);
linkedHashMap.put("王五",25);
linkedHashMap.put("李四",23);
linkedHashMap.put("张飞",20);
linkedHashMap.put("赵六",28);
linkedHashMap.put("李四",24);
System.out.println(linkedHashMap.size());// 5 是不重复的 要是键一样,值会被后面的覆盖
//有序表现在: 输入和输出的顺序的一样的
System.out.println(linkedHashMap);//{张三=22, 王五=25, 李四=24, 张飞=20, 赵六=28}
2.6 TreeMap
特点:排序、不重复、无索引 (按照键的大小默认升序排序,只能对键排序)
让类实现Comparable接口,重写比较规则。
TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则。
//TreeMap 排序、不重复、无索引 排序是键的排序,按ASCII码排序,第一个相同的比较第二个,以此类推
Map<String,Integer> treeMap = new TreeMap<>();
treeMap.put("Java基础",22);
treeMap.put("pht",25);
treeMap.put("Mysql",52);
treeMap.put("Python",72);
treeMap.put("pht",23);
System.out.println(treeMap.size());// 4 pth 23
System.out.println(treeMap);//Java基础=22, Mysql=52, Python=72, pht=23
三补充知识:集合的嵌套
ArraryList 嵌套 ArraryList
ArraryList<ArraryList<String>>
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三","李四","王五");
ArrayList<String> list1 =new ArrayList<>();
Collections.addAll(list1,"汤姆","joker","赵六");
//再创建一个集合存放两个list
ArrayList<ArrayList<String>> arrayLists = new ArrayList<>();
arrayLists.add(list);
arrayLists.add(list1);
for (ArrayList<String> arrayList : arrayLists) {
for (String s : arrayList) {
System.out.println(s);
}
}
}
ArraryList嵌套Map
ArraryList<Map<String,String>>
public static void main(String[] args) {
//1.创建两个map存放两个班级的学生(学号、姓名)
Map<String,String> map = new HashMap<>();
map.put("001","张飞");
map.put("002","王五");
Map<String,String> map1 = new HashMap<>();
map1.put("001","赵丽");
map1.put("002","林冲");
//2.创建一个list存
ArrayList<Map<String,String>> arrayList = new ArrayList<>();
arrayList.add(map);
arrayList.add(map1);
//3.遍历输出里学生信息
for (Map<String, String> map2 : arrayList) {
//3.1遍历map集合
Set<String> set = map2.keySet();
for (String s : set) {
System.out.println("学号:"+s+" 姓名:"+map2.get(s));
}
}
}
Map嵌套AarraryList
HashMap<String, ArrayList<Person>>
ArrayList< HashMap<String, String>>
public static void main(String[] args) {
List<String> cities1 = new ArrayList<>();
Collections.addAll(cities1,"南京","扬州市","苏州市","无锡市","常州市");
List<String> cities2 = new ArrayList<>();
Collections.addAll(cities2,"武汉市","孝感市","十堰市","宜昌市","鄂州市");
List<String> cities3 = new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();
Collections.addAll(cities3,"石家庄京","唐山市","邢台市","保定市","张家口市");
map.put("江苏省",cities1);
map.put("湖北省",cities2);
map.put("河北省",cities3);
map.forEach((k,v)->{
System.out.print(k+" = ");
v.forEach((value)->{
System.out.print(value+"\t");
});
System.out.println();
});
}
Map集合嵌套
HashMap<String, HashMap<Person,String>>
public static void main(String[] args) {
//存放两个年纪学生的信息
Map<String,String> map = new HashMap<>();
map.put("201","张飞");
map.put("202","李四");
map.put("203","王五");
Map<String, String> map1 = new HashMap<>();
map1.put("101","邵阳");
map1.put("102","米彩");
map1.put("103","乐瑶");
//创建一个Map集合存放
Map<String,Map<String,String>> bigMap = new HashMap<>();
bigMap.put("二年级",map);
bigMap.put("一年级", map1);
//输出学生内容
bigMap.forEach((k,v)->{
System.out.println("级别:"+k);
Set<String> set = v.keySet();//获取到学生信息map里面的键
for (String s : set) {
System.out.println("学号:"+s+" 姓名:"+v.get(s));
}
});
}