Set系列集合
Set系列集概述
public class Test {
public static void main(String[] args) {
// Set系列集合的特点 HashSet LinkedHashSet TreeSet
// 无序 不重复 无索引
HashSet<String> sets = new HashSet<>();
// 有序 不重复 无索引
// HashSet<String> sets = new LinkedHashSet<>();
sets.add("MySQL");
sets.add("MySQL");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
System.out.println(sets);
}
}
HashSet元素无序的底层原理:哈希表
public class Test {
public static void main(String[] args) {
// 学会获取对象的哈希值
String s = "Java";
System.out.println(s.hashCode());
String s1 = "Java1";
System.out.println(s1.hashCode());
}
}
HashSet元素重复的底层原理
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;
}
/**
* 只要两个对象内容一样,结果一定是true
* @param o
* @return
*/
@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);
}
/**
*
* @return
*/
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex
;
}
}
public class Test {
public static void main(String[] args) {
// Set集合去重复原因:先判断哈希值,再判断equals
Set<Student> sets = new HashSet<>();
Student s1 = new Student("张三" ,20 ,'男');
Student s2 = new Student("李四" ,21 ,'男');
Student s3 = new Student("张三" ,20 ,'男');
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
sets.add(s1);
sets.add(s2);
sets.add(s3);
System.out.println(sets);
}
}
实现类:LinkedHashSet
实现类:TreeSet
public class Test {
public static void main(String[] args) {
Set<Integer> sets = new TreeSet<>(); // 不重复 无索引 可排序
sets.add(3);
sets.add(4);
sets.add(1);
sets.add(2);
System.out.println(sets);
Set<String> sets1 = new TreeSet<>(); // 不重复 无索引 可排序
sets1.add("b");
sets1.add("c");
sets1.add("d");
sets1.add("a");
System.out.println(sets1);
// 结果:
// [1, 2, 3, 4]
// [a, b, c, d]
}
}
package com.test;
import java.util.Comparator;
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 +
'}';
}
/**
* 方式一:类自定义比较规则
* @param o
* @return
*/
@Override
public int compareTo(Apple o) {
// 按重量比较
return (this.weight - o.weight); //去掉重量一样的元素
// return (this.weight - o.weight) >= 0 ? 1 : -1; //保留重量一样的元素
}
}
public class Test {
public static void main(String[] args) {
// 方式二:集合自带比较器对象进行规则制定
//shift + F6:快速改名
Set<Apple> apples = new TreeSet<>(( o1, o2) -> (Double.compare(o1.getPrice(), o2.getPrice())));
apples.add(new Apple("红富士" ,"红色" ,9.9 ,500));
apples.add(new Apple("青苹果" ,"绿色" ,9.9 ,300));
apples.add(new Apple("黄元帅" ,"青色" ,29.9 ,400));
apples.add(new Apple("洛川苹果" ,"黄色" ,9.8 ,500));
System.out.println(apples);
}
}
Collection体系的特点、使用场景总结
补充知识:可变参数
public class Test {
public static void main(String[] args) {
// 不传参数
sum();
// 传一个或多个
sum(1);
sum(2 ,3);
// 传一个数组
sum(new int[]{1, 2});
}
public static void sum(int... nums) {
//注意:可变数组再方法内部其实就是一个数组
System.out.println("元素个数 " + nums.length);
System.out.println("元素内容 " + Arrays.toString(nums));
}
}
补充知识:集合工具类Collections
Collection体系的综合案例
public class Card {
private String size;
private String color;
private int index; // 牌的真正大小
public Card() {
}
public Card(String size, String color ,int index) {
this.size = size;
this.color = color;
this.index = index;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public String toString() {
return color + size;
}
}
/**
目标:斗地主游戏的案例开发。
业务需求分析:
斗地主的做牌, 洗牌, 发牌, 排序(拓展知识), 看牌。
业务: 总共有54张牌。
点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2"
花色: "♠", "♥", "♣", "♦"
大小王: "👲" , "🃏"
点数分别要组合4种花色,大小王各一张。
斗地主:发出51张牌,剩下3张作为底牌。
功能:
1.做牌。
2.洗牌。
3.定义3个玩家
4.发牌。
5.排序(拓展,了解,作业)
6.看牌
*/
public class GameDemo {
/**
* 1. 定义一个静态的集合存储54张牌
*/
public static List<Card> allCards = new ArrayList<>();
/**
* 2. 定义静态代码块初始化牌数据
*/
static {
// 3. 定义点数:个数确定类型确定,使用数组
String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
// 4. 定义花色:个数确定类型确定,使用数组
String[] colors = {"♠", "♥", "♣", "♦"};
// 5. 组合点数和花色
int index = 0; //记录牌的大小
for (String size : sizes) {
index++;
for (String color : colors) {
// 6. 封装成一个牌对象
Card c = new Card(size ,color ,index);
// 7. 存入集合容器中去
allCards.add(c);
}
}
// 8. 大小王单独加
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) {
// 9. 洗牌
Collections.shuffle(allCards);
System.out.println("洗牌后:" + allCards);
// 10. 发牌(定义三个玩家,每个玩家也是一个集合容器)
List<Card> zhang = new ArrayList<>();
List<Card> li = new ArrayList<>();
List<Card> wang = new ArrayList<>();
// 11. 开始发牌(把51张牌发给玩家,剩余3张作为底牌)
for (int i = 0; i < allCards.size() - 3; i++) {
// 先拿到当前牌对象
Card c = allCards.get(i);
// 发牌
if(i % 3 == 0){
zhang.add(c);
}else if(i % 3 == 1){
li.add(c);
}else if(i % 3 == 2){
wang.add(c);
}
}
// 12. 拿到最后三张底牌
List<Card> lastThreeCards = allCards.subList((allCards.size() - 3) , (allCards.size()));
// 13. 给玩家的牌排序(从大到小)
sortCards(zhang);
sortCards(li);
sortCards(wang);
sortCards(lastThreeCards);
// 14. 输出玩家的牌
System.out.println("zhang: " + zhang);
System.out.println("li: " + li);
System.out.println("wang: " + wang);
System.out.println("三张底牌: " + lastThreeCards);
}
/**
* 给牌排序
* @param cards
*/
private static void sortCards(List<Card> cards) {
Collections.sort(cards, ( o1, o2 ) -> (o2.getIndex() - o1.getIndex()));
}
}
Map集合体系
Map集合的概述
Map集合体系特点
public class Test {
public static void main(String[] args) {
// HashMap
// Map<String ,Integer> maps = new HashMap<>();
// LinkedHashMap
Map<String ,Integer> maps = new LinkedHashMap<>();
maps.put("鸿星尔克" ,3);
maps.put("Java" ,1);
maps.put("Java" ,100); //覆盖前面的数据
maps.put(null ,null);
System.out.println(maps);
}
}
Map集合常用API
public class Test {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map<String , Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
// {huawei=100, 手表=10, 生活用品=10, iphoneX=100, 娃娃=20}
System.out.println(maps);
// 2.清空集合
// maps.clear();
// System.out.println(maps);
// 3.判断集合是否为空,为空返回true ,反之!
System.out.println(maps.isEmpty());
// 4.根据键获取对应值:public V get(Object key)
Integer key = maps.get("huawei");
System.out.println(key);
// 5.根据键删除整个元素。(删除键会返回键的值)
System.out.println(maps.remove("iphoneX"));
System.out.println(maps);
// 6.判断是否包含某个键 ,包含返回true ,反之
System.out.println(maps.containsKey("huawei"));
// 7.判断是否包含某个值。
maps.containsValue(100);
// {huawei=100, 手表=10, 生活用品=10, 娃娃=20}
// 8.获取全部键的集合:public Set<K> keySet()
Set<String> keys = maps.keySet();
System.out.println(keys);
// 9.获取全部值的集合:Collection<V> values();
Collection<Integer> values = maps.values();
System.out.println(values);
// 10.集合的大小
System.out.println(maps.size());
// 11.合并其他Map集合。(拓展)
Map<String ,Integer> map1 = new HashMap<>();
map1.put("Java1" ,1);
map1.put("Java2" ,100);
Map<String ,Integer> map2 = new HashMap<>();
map2.put("Java2" ,1);
map2.put("Java2" ,100);
map1.putAll(map2); // 把集合map2的元素拷贝一份到map1中去
System.out.println(map1);
System.out.println(map2);
}
}
Map集合的遍历方式一:键找值
public class Test {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map<String , Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
// {huawei=100, 手表=10, 生活用品=10, iphoneX=100, 娃娃=20}
//先拿到集合的全部键
Set<String> keys = maps.keySet();
//遍历每个键,根据键提取值
for (String key : keys) {
int value = maps.get(key);
System.out.println(key + " " + value);
}
}
}
Map集合的遍历方式二:键值对
public class Test {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map<String , Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
// 将Map转坏为Set ctrl + alt + v
Set<Map.Entry<String, Integer>> entries = maps.entrySet();
// 开始遍历
for (Map.Entry<String, Integer> entry :entries) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " " + value);
}
}
}
Map集合的遍历方式三:lambda表达式
public class Test {
public static void main(String[] args) {
// 1.添加元素: 无序,不重复,无索引。
Map<String , Integer> maps = new HashMap<>();
maps.put("iphoneX",10);
maps.put("娃娃",20);
maps.put("iphoneX",100);// Map集合后面重复的键对应的元素会覆盖前面重复的整个元素!
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",10);
maps.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String key, Integer value) {
System.out.println(key + " " + value);
}
});
}
}
public class Test {
public static void main(String[] args) {
Random r = new Random();
// 把80个学生选择的数据拿进来
String[] selects = {"A" ,"B" ,"C" ,"D"};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 80; i++) {
sb.append(selects[r.nextInt(selects.length)]);
}
System.out.println(sb);
// 定义一个Map集合 记录最终统计结果
Map<Character ,Integer> infos = new HashMap<>();
// 遍历80个学生选择的数据
for (int i = 0; i < sb.length(); i++) {
// 提取当前选择景点字符
char ch = sb.charAt(i);
// 判断Map是否存在这个键
if (infos.containsKey(ch)) {
infos.put(ch ,infos.get(ch) + 1);
} else {
// 说明此景点第一次被统计
infos.put(ch ,1);
}
}
// 输出集合
System.out.println(infos);
}
}
Map集合的实现类HashMap
Map集合的实现类LinkedHashMap
Map集合的实现类TreeMap
补充知识:集合的嵌套
public class Test {
public static void main(String[] args) {
// 要求程序记录每个学生使用的情况
// 使用一个Map集合
Map<String ,List<String>> data = new HashMap<>();
// 把学生选择的数据存入进去
List<String> select = new ArrayList<>();
Collections.addAll(select ,"A", "C");
data.put("张三",select);
List<String> select1 = new ArrayList<>();
Collections.addAll(select1 ,"A", "B" ,"C");
data.put("李四",select1);
System.out.println(data);
// 统计每个景点选择的人数
Map<String ,Integer> infos = new HashMap<>();
// 提取所有人选择的景点信息
Collection<List<String>> values = data.values();
System.out.println(values);
for (List<String> value : values) {
for (String s : value) {
// 有没有包含景点
if (infos.containsKey(s)) {
infos.put(s ,infos.get(s) + 1);
}else {
infos.put(s ,1);
}
}
}
System.out.println(infos);
}
}