目录
一、Set系列集合概述、Collection体系的特点、使用场景总结
一、Set系列集合概述、Collection体系的特点、使用场景总结
1.Set系列集合概述
Set系列集合特点:1.无序:存储顺序不一样;2.不重复:可以去除重复;3.五索引:没有索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
Set集合实现类的特点:1.HashSet:无序、不重复、无索引;2.LinkedHashSet:有序、不重复、无索引;3.TreeSet:排序、不重复、无索引
package com.pikaqiu.d1_set;
import java.util.HashSet;
import java.util.Set;
public class SetDemo1 {
public static void main(String[] args) {
Set<String> sets = new HashSet<>();
sets.add("Mysql");
sets.add("Mysql");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
System.out.println(sets); //[Java, Mysql, HTML]
}
}
2.HashSet元素无序的底层原理:哈希表
HashSet底层原理:1.HashSet集合底层采取哈希表存储的数据;2.哈希表是一种对于增删改查数据性能都较好的结构
哈希表的组成:JDK8之前,底层使用数组+链表组成;JDK8开始之后,底层采用数组+链表+红黑树组成
哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数据
Object类的API:public int hashCode():返回对象的哈希值
对象的哈希值特点:1.同一个对象多次调用hashCode()方法返回发哈希值是相同的;2.默认情况下,不同对象的哈希值是不同的
3.HashSet元素去重复的底层原理
package com.pikaqiu.d1_set;
import java.util.Objects;
public class Student {
private String name;
private int age;
private char sex;
public Student() {
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && sex == student.sex && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
package com.pikaqiu.d1_set;
import java.util.HashSet;
import java.util.Set;
public class SetDemo3 {
public static void main(String[] args) {
Set<Student> sets = new HashSet<>();
Student s1 = new Student("张三",20,'男');
Student s2 = new Student("张三",20,'男');
Student s3 = new Student("李四",21,'男');
sets.add(s1);
sets.add(s2);
sets.add(s3);
System.out.println(sets); //[Student{name='李四', age=21, sex=男}, Student{name='张三', age=20, sex=男}]
}
}
4.实现类:LinkedHashSet
5.实现类:TreeSet
自定义排序规则:TreeSet集合存储对象的时候有2种方法可以设计自定义比较规则
方式一:让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来指定比较规则;
方式二:TreeSet集合有参构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则
注意:如果TreeSet集合存储的对象有实现比较规则,集合自带比较器,默认使用集合自带的比较器排序
package com.pikaqiu.set;
public class Apple implements Comparable<Apple>{
private String name;
private String color;
private double price;
private int weight;
public Apple() {
}
public Apple(String name, String color, double price, int weight) {
this.name = name;
this.color = color;
this.price = price;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Apple{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", price=" + price +
", weight=" + weight +
'}';
}
/**
* 方式一:类自定义比较规则
* o1.compareTo(o2)
* @param o
* @return
*/
@Override
public int compareTo(Apple o) {
//按重量进行比较
return this.weight - o.weight;
//return this.weight - o.weight >= 0 ? 1:-1; //保留重复的元素
}
}
package com.pikaqiu.set;
import jdk.management.resource.internal.inst.AbstractPlainDatagramSocketImplRMHooks;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo4 {
public static void main(String[] args) {
Set<Integer> sets = new TreeSet<>(); //不重复,无索引,可排序
sets.add(18);
sets.add(20);
sets.add(16);
sets.add(28);
sets.add(25);
System.out.println(sets); //从小到大 [16, 18, 20, 25, 28]
Set<String> sets1 = new TreeSet<>();
sets1.add("Java");
sets1.add("Java");
sets1.add("about");
sets1.add("C++");
sets1.add("Python");
sets1.add("Python");
sets1.add("C#");
System.out.println(sets1); //按字符编号顺序排序 [C#, C++, Java, Python, about]
System.out.println("---------------------------");
//方式二:集合自带比较器对象进行规则制定
Set<Apple> apples = new TreeSet<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
//return o2.getWeight() - o1.getWeight(); //降序
//注意:浮点型建议直接使用Double.compare进行比较
return Double.compare(o2.getPrice(),o1.getPrice()); //价格降序
}
});
apples.add(new Apple("红富士","红色",9.9,500));
apples.add(new Apple("青苹果","绿色",15.9,300));
apples.add(new Apple("绿苹果","青色",29.9,400));
apples.add(new Apple("毒苹果","紫色",19.9,500));
System.out.println(apples);
}
}
二、 补充知识:可变参数
可变参数:可变参数在形参中可以接收多个数据;可变参数的格式:数据类型...参数名称
可变参数的作用:传输参数非常灵活,方便。可以不传输参数,可以传输1个或者多个,也可以传输一个数组;可变参数在方法内部本质上是一个数组。
可变参数的注意事项:1.一个形参列表中可变参数只能有一个;2.可变参数必须放在形参列表的最后面
package com.pikaqiu.params;
import java.util.Arrays;
public class MethodDemo {
public static void main(String[] args) {
sum(); //不传参数
sum(10); //可以传输一个参数
sum(10,20,30); //可以传输多个参数
sum(new int[]{10,20,30,40,50}); //可以传输一个数组
}
public static void sum(int ... nums){
//注意:可变参数内部其实就是一个数组
System.out.println("元素个数:" + nums.length);
System.out.println("元素内容:" + Arrays.toString(nums));
}
}
三、补充知识:集合工具类Collections
package com.pikaqiu.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo1 {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
// names.add("张三");
// names.add("李四");
// names.add("王五");
Collections.addAll(names,"张三","李四","王五");
System.out.println(names);
//打乱集合顺序
Collections.shuffle(names);
System.out.println(names);
}
}
四、Collection体系的综合案例
斗地主游戏:在启动游戏房间的时候,应提前准备好54张牌,完成洗牌、发牌、牌排序、逻辑。
package com.pikaqiu.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CardTest {
//定义静态的集合存储54张牌对象
public static List<Card> allCards = new ArrayList<>();
//定义静态代码块初始化牌数量
static {
//定义点数
String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2",};
//定义花色
String[] colors = {"♠","♥","♣","♦"};
//组合点数和花色
int index = 0; //记录牌大小
for (String s : sizes) {
index++;
for (String s1 : colors) {
//封装成牌对象
Card c = new Card(s,s1,index);
allCards.add(c);
}
}
//大小王
Card c1 = new Card("","🃏",++index);
Card c2 = new Card("","🃏",++index);
Collections.addAll(allCards,c1,c2);
System.out.println("新牌:" + allCards);
}
public static void main(String[] args) {
//洗牌
Collections.shuffle(allCards);
System.out.println("洗牌后:" + allCards);
//发牌
List<Card> zhangsan = new ArrayList<>();
List<Card> lisi = new ArrayList<>();
List<Card> wangwu = new ArrayList<>();
//开始发牌
for (int i = 0; i < allCards.size()-3; i++) {
Card c = allCards.get(i);
if(i%3 == 0){
zhangsan.add(c);
}else if(i%3 == 1){
lisi.add(c);
}else if(i%3 == 2){
wangwu.add(c);
}
}
//拿到最后三张牌
List<Card> last = allCards.subList(allCards.size() - 3,allCards.size());
//牌排序
sortCards(zhangsan);
sortCards(lisi);
sortCards(wangwu);
//输出
System.out.println("张三:" + zhangsan);
System.out.println("李四:" + lisi);
System.out.println("王五:" + wangwu);
System.out.println("最后三张牌:" + last);
}
private static void sortCards(List<Card> cards) {
Collections.sort(cards, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o1.getIndex()-o2.getIndex();
}
});
}
}
五、Map集合体系
1.Map集合的概述
Map集合概述和使用:Map集合是一种双列集合,每个元素包含两个数据;Map集合的每个元素的格式:key=value(键值对元素);Map集合也被称为"键值对集合"。
Map集合整体格式:{key1=value1,key2=value2,key3=value3,...}
2.Map集合体系特点
package com.pikaqiu.map;
import java.util.HashMap;
import java.util.Map;
public class MapDemo1 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("鸿星尔克",3);
maps.put("Java",3);
maps.put("Java",100);
maps.put(null,null);
System.out.println(maps); //{null=null, Java=100, 鸿星尔克=3}
}
}
3.Map集合常用的API
package com.pikaqiu.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo2 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",20);
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps); //{huawei=100, 手表=10, 生活用品=10, iphoneX=20, 娃娃=20}
//清空集合
// maps.clear();
// System.out.println(maps); //{}
//判空,真返回true
System.out.println(maps.isEmpty());
//根据键获取对应值
Integer key = maps.get("huawei");
System.out.println(key); //100
System.out.println(maps.get("生活用品")); //10
System.out.println(maps.get("iphone")); //null
//根据键删除整个元素(回返回值)
System.out.println(maps.remove("iphoneX")); //20
System.out.println(maps); //{huawei=100, 手表=10, 生活用品=10, 娃娃=20}
//判断是否包含某个键
System.out.println(maps.containsKey("huawei")); //true
//判断是否包含某个值
System.out.println(maps.containsValue(20)); //true
System.out.println(maps.containsValue(200)); //false
//获取全部键的集合
Set<String> keys = maps.keySet();
System.out.println(keys); //[huawei, 手表, 生活用品, 娃娃]
//获取全部值的集合
Collection<Integer> values = maps.values();
System.out.println(values); //[100, 10, 10, 20]
//集合的大小
System.out.println(maps.size()); //4
//合并map集合
Map<String,Integer> map1 = new HashMap<>();
map1.put("java",1);
map1.put("mysql",2);
Map<String,Integer> map2 = new HashMap<>();
map2.put("java1",1);
map2.put("mysql1",2);
map1.putAll(map2); //把map2中的元素拷贝到map1中
System.out.println(map1); //{mysql1=2, java=1, mysql=2, java1=1}
System.out.println(map2); //{mysql1=2, java1=1}
}
}
4.Map集合的遍历方式之一:键找值
package com.pikaqiu.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo3 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",20);
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
//先拿到集合的全部键
Set<String> keys = maps.keySet();
//遍历每个键,根据键找值
for(String key : keys){
int value = maps.get(key);
System.out.print(key + "->" + value + " ");
}
System.out.println();
}
}
5.Map集合的遍历方式之二:键值对
package com.pikaqiu.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo3 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",20);
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
//把Map集合转变为Set集合
Set<Map.Entry<String, Integer>> entries = maps.entrySet();
//遍历
for(Map.Entry<String,Integer> entry : entries){
String key = entry.getKey();
int value = entry.getValue();
System.out.print(key + "->" + value + " "); //huawei->100 手表->10 生活用品->10 iphoneX->20 娃娃->20
}
System.out.println();
}
}
6.Map集合的遍历方式之三:lambda表达式
package com.pikaqiu.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MapDemo3 {
public static void main(String[] args) {
Map<String,Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",20);
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// maps.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String key, Integer value) {
// System.out.print(key + "->" + value + " "); //huawei->100 手表->10 生活用品->10 iphoneX->20 娃娃->20
// }
// });
maps.forEach((key,value) -> {
System.out.print(key + "->" + value + " ");
}); //huawei->100 手表->10 生活用品->10 iphoneX->20 娃娃->20);
}
}