Set系列集合、Map集合体系

Set系列集合特点:
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普遍for循环遍历,也不能通过索引来获取元素
Set集合实现类特点:
HashSet:无序,不重复,无索引
LinkedHashSet:有序,不重复,无索引
TreeSet:排序、不重复、无索引
Set集合的功能基本上与Collection的API一致
package com.itheima.d1_set;
import java.util.HashSet;
import java.util.Set;
public class SetDemo1 {
public static void main(String[] args) {
//查看Set系列集合的特点:HashSet LinkedHashSet TreeSet
//无序,不重复,无索引
Set<String> sets=new HashSet<>();
sets.add("MySql");
sets.add("MySql");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
sets.add("SpringBoot");
sets.add("SpringBoot");
System.out.println(sets);//[Java, MySql, HTML, SpringBoot]
}
}
package com.itheima.d1_set;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class SetDemo1 {
public static void main(String[] args) {
//查看Set系列集合的特点:HashSet LinkedHashSet TreeSet
//无序,不重复,无索引
Set<String> sets=new LinkedHashSet<>();
sets.add("MySql");
sets.add("MySql");
sets.add("Java");
sets.add("Java");
sets.add("HTML");
sets.add("HTML");
sets.add("SpringBoot");
sets.add("SpringBoot");
System.out.println(sets);//[MySql, Java, HTML, SpringBoot]
}
}
Set系列集合的特点:
无序、不重复、无索引
Set集合的实现类特点
HashSet无序,不重复,无索引
LinkedHashSet:有序,不重复,无索引
TreeSet:可排序,不重复,无索引
HashSet底层原理:
HashSet集合底层采取哈希表存储的数据
哈希表是一种对于增删改查数据性能都较好的结构
哈希表的组成:
JDK8之前,底层使用数组+链表组成
JDK8之后,底层采用数组+链表+红黑树组成
在了解哈希表之前需要先理解哈希值的概念
哈希值:
是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object类型的API:
public int hashCode():返回对象的哈希值
对象的哈希值特点:
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的








package com.itheima.d1_set;
import java.util.Set;
import java.util.TreeSet;
/*目标:观察TreeSet对于有值特性的数据如和排序
* 学会使用自定以类型的对象进行指定规则排序*/
public class SetDemo4 {
public static void main(String[] args) {
Set<Integer> sets=new TreeSet<>();//不重复 无索引 可排序
sets.add(23);
sets.add(78);
sets.add(19);
sets.add(36);
System.out.println(sets);//19 23 36 78
Set<String> sets1=new TreeSet<>();//不重复 无索引 可排序
sets1.add("cba");//根据首字母在ASCLL码表排序的
sets1.add("Java");
sets1.add("Abc");
sets1.add("bcs");
System.out.println(sets1);//Abc bcs cba
}
}

package com.itheima.d1_set;
public class Apple implements Comparable<Apple>{
private String name;
private String color;
private double price;
private int weight;
@Override
public String toString() {
return "Apple{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", price=" + price +
", weight=" + 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;
}
/**
* 方法一:类自定义比较规则
* @param o
* @return
*/
@Override
public int compareTo(Apple o) {
//按照重量进行比较的
return this.weight-o.weight>=0?1:-1;
}
}
package com.itheima.d1_set;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
/*目标:观察TreeSet对于有值特性的数据如和排序
* 学会使用自定以类型的对象进行指定规则排序*/
public class SetDemo4 {
public static void main(String[] args) {
Set<Integer> sets=new TreeSet<>();//不重复 无索引 可排序
sets.add(23);
sets.add(78);
sets.add(19);
sets.add(36);
System.out.println(sets);//19 23 36 78
Set<String> sets1=new TreeSet<>();//不重复 无索引 可排序
sets1.add("cba");//根据首字母在ASCLL码表排序的
sets1.add("Java");
sets1.add("Abc");
sets1.add("bcs");
System.out.println(sets1);//Abc Java bcs cba
System.out.println("---------------");
Set<Apple> apples=new TreeSet<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
//return o1.getWeight()-o2.getWeight();升序
//return o2.getWeight()-o2.getWeight();//降序
//注意:浮点型建议直接使用Double.compare进行比较
return Double.compare(o1.getPrice(),o2.getPrice());
}
});
Set<Apple> apples=new TreeSet<>((o1,o2) -> Double.compare(o2.getPrice(), o1.getPrice()) );
apples.add(new Apple("红富士","红色",9.9,500));
apples.add(new Apple("青苹果","青色",15.9,400));
apples.add(new Apple("黄苹果","黄色",17,450));
apples.add(new Apple("绿苹果","绿色",29.7,400));
System.out.println(apples);//[Apple{name='青苹果', color='青色',
// price=15.9, weight=300}, Apple{name='绿苹果', color='绿色',
// price=29.7, weight=400}, Apple{name='黄苹果', color='黄色',
// price=17.0,
// weight=450}, Apple{name='红富士', color='红色', price=9.9,
// weight=500}]
}
}
TreeSet集合的特点是怎样的?
可排序,不重复,无索引
底层基于红黑树实现排序,增删改查性能较好
TreeSet集合自定义排序桂希恩有几种方式?
2种
类实现Comparable接口,重写比较规则
集合自定义Comparable比较器对象,重写比较规则

可变参数:
可变参数用在形参中可以接受多个数据
可变参数的格式:数据类型...参数名称
可变参数的作用:
传输参数非常灵活,方便。可以不传参数,可以传输1个或者多个,也可以传输一个数组


斗地主游戏:
package com.itheima.d3_coolection_test;
public class Card {
private String size;
private String color;
private int index;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public String toString() {
return size+color;
}
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;
}
}
package com.itheima.d3_coolection_test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GameDemo {
/*定义一个静态的集合存储54张牌对象*/
public static List<Card> allCards=new ArrayList<>();
//作牌:定义静态代码块初始化牌的数据
static{
//3.定义点数:小数确定,类型确定,使用数据
String[] sizes={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
//定义花色,个数确定,类型确定,使用数组
String[] colors={"♦","♥","♣","♠"};
//综合点数和花色
int index=0;
for(String size:sizes){
index++;
for(String color:colors){
//封装成一个牌对象
Card c=new Card(size,color,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) {
//9.洗牌
Collections.shuffle(allCards);
System.out.println("洗牌后:"+allCards);
//10:发牌:定义三个玩家,每个玩家的拍色也是一个集合容器
List<Card> linghuchong=new ArrayList<>();
List<Card> jiumozhi=new ArrayList<>();
List<Card> renyingying=new ArrayList<>();
//11.开始发牌,从牌集合中发出51张牌给三个玩家,剩余3张作为底牌
for (int i = 0; i < allCards.size()-3; i++) {
//先拿到当前牌对象
Card c=allCards.get(i);
if(i%3==0){
linghuchong.add(c);
}else if(i%3==1){
jiumozhi.add(c);
}else if(i%3==2){
renyingying.add(c);
}
}
//拿到最后三张底牌
List<Card> lastThreeCards=allCards.subList(allCards.size()-3,allCards.size());
//给玩家的牌排序(从大到小 可以自己先试一试)
sortCards(linghuchong);
sortCards(jiumozhi);
sortCards(renyingying);
//输出玩家的牌
System.out.println("啊冲:"+linghuchong);
System.out.println("啊久:"+jiumozhi);
System.out.println("盈盈:"+renyingying);
System.out.println("三张底牌:"+lastThreeCards);
}
//给牌排序
private static void sortCards(List<Card> cards) {
Collections.sort(cards, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o2.getIndex()- o1.getIndex();
}
});
}
}
Map集合概述和使用:
Map集合是一种双列集合,每个元素包含两个数据
Map集合的每个元素的格式:key=value(键值对元素)
Map集合也称为"键值对集合"
Map集合整体格式:
Collection集合的格式:[元素1,元素2,元素3...]
Map集合的完整格式:[key1=value1,key2=value2,key3=value3,.....]
Map集合的使用场景之一:
购物车提供的四个商品和购买的数量在后台需要容器存储
每个商品对象都一一对应一个购买数量
把商品对象看成是Map集合的键,购买数量看成Map集合的值
{商品1=2,商品2=3,商品3=4,商品4=3}
Map集合是什么?使用场景是什么样的?
Map集合是键值对集合
Map集合非常适合做类购物车这样的业务场景
Map集合体系特点:

Map集合的键无序,不重复的 Map集合的值不做要求可以重复
Map集合体系特点:
Map集合的特点都是由键决定的
Map集合的键是无序的,不重复的,无索引的,只可以不做要求(可以重复)
Map集合后面重复的键对应的值会覆盖前面重复的键
Map集合的键值对都可以为null
Map集合实现类特点:
HashMap:元素按照键是无序,不重复,无索引,值不做要求(与Map体系一致)
package com.itheima.d5_map;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
//识别Map体系的特点:按照键无序,不重复,无索引,值不做要求
public class MapDemo1 {
public static void main(String[] args) {
//创建一个Map集合对象,maps添加的方式是put
//Map<String, Integer> maps = new HashMap<>();
Map<String,Integer> maps=new LinkedHashMap<>();
maps.put("鸿星尔克",3);
maps.put("枸杞",1);
maps.put("Java",100);
maps.put("枸杞",100);
maps.put(null,null);//如果前面的键与后面的键相同,那么后面的值将覆盖前面的值
System.out.println(maps);//{鸿星尔克=3, 枸杞=100, Java=100, null=null}
}
}
Map集合的特点:
HashMap:元素按照键是无序,不重复,无索引,值不做要求(与Map体系一致)
LinkedHashMap:元素按照是有序,不重复,无索引,值不做要求
TreeMap:元素按照键是排序,不重复的,无索引的,值不做要求
Map集合:
Map是双列集合的祖宗接口,他的功能是全部双列集合都可以继承使用的

package com.itheima.d5_map;
import java.util.*;
public class MapDemo2 {
public static void main(String[] args) {
//1.添加元素:无序,不重复,无索引
Map<String, Integer> maps = new HashMap<>();
maps.put("iphoneX",10);//Map集合后面重复的键对于的元素会
// 覆盖前面重复的个数
maps.put("娃娃",31);
maps.put("iphoneX",100);
maps.put("huawei",100);
maps.put("生活用品",10);
maps.put("手表",102);
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);
System.out.println(maps.get("生活用品"));
System.out.println(maps.get("你好"));
//5.根据键删除整个元素(删除键会返回键的值)
System.out.println(maps.remove("iphoneX"));
System.out.println(maps);
//6.判断是否包含某个键,包含返回true.反之
System.out.println(maps.containsKey("娃娃"));
System.out.println(maps.containsKey("iphoneX"));
//7.判断是否包含某个值
System.out.println(maps.containsValue(10));
System.out.println(maps.containsValue(100));
//8.获取全部键的集合,public Set<K> keySet()
Set<String> keys=maps.keySet();
System.out.println(keys);
System.out.println("-----------------");
//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);
map1.put("java2",101);
Map<String, Integer> map2 = new HashMap<>();
map2.put("java2",1);
map2.put("java3",100);
map1.putAll(map2);
System.out.println(map1);
System.out.println(map2);
}
}
Map集合的遍历方式一:键找值

package com.itheima.d5_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("娃娃",30);
maps.put("iphoneX",100);
maps.put("huiwei",1000);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
//{手表=10, 生活用品=10, huiwei=1000, iphoneX=100, 娃娃=30}
//1.键找值:第一步:先拿到集合的全部键
Set<String> keys=maps.keySet();
//2.第二步:遍历每个键,根据键提取值
for(String key:keys){
//调用maps中的get方法得到键
int value=maps.get(key);
System.out.println(key+"==>"+value);
}
}
}
遍历Map集合方式二:键值对
先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了
遍历Set集合,然后提取键以及提取值

package com.itheima.d5_map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo4 {
public static void main(String[] args) {
Map<String,Integer> maps=new HashMap<>();
maps.put("娃娃",30);
maps.put("iphoneX",100);
maps.put("huawei",88);
maps.put("生活用品",10);
maps.put("手表",10);
System.out.println(maps);
//Set<Map.Entry<String,Integer>> entries=maps.entrySet();
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
得益于JDK8开始的新技术Lambda表达式。提供了一种更简单,更直接的遍历集合的方式
Map结合Lambda遍历的API
default void forEach(BiConsumer<? super K,? super V>action>) 结合lambda遍历Map集合
package com.itheima.d6_map_test;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
//需求:统计投票人数
public class MapTest1 {
public static void main(String[] args) {
//1.把80个学生选择的数据拿进来
String[] selects={"A","B","C","D"};
//定义一个StringBuilder的对象
StringBuilder sb=new StringBuilder();
//获取一个随机数对象
Random ra = new Random();
//定义一个循环
for (int i = 0; i < 80; i++) {
//用StringBuilder的对象名添加学生,selects添加的数组值为随机数
sb.append(selects[ra.nextInt(selects.length)]);
}
System.out.println(sb);
//定义一个Map集合记录最终统计的结果 A=30
Map<Character ,Integer> infos=new HashMap<>();//{}
//3.遍历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);
}
}















