JavaSE基础进阶学习day10

Set系列集合

一.Set系列集合集概述

1Set系列集合特点:
(1)无序:存取顺序不一致
(2)不重复:可以去除重复
(3)无索引:没有带索引的方法,所以不能使用普通for循环比那里,也不能通过索引来获取元素

2Set系列实现类特点
(1)HashSet:无序、不重复、无索引
(2)LinkedHashSet:有序、不重复、无索引
(3)TreeSet:排序、不从负、无索引

3Set集合的功能上基本与Collection的API一致

4总结:
(1)Set系列集合的特点
        (I)无序、不重复、无索引

(2)Set集合的实现类特点
        (I)HashSet:无序、不重复、无索引
        (II)LinkedHashSet:有序、不重复、无索引
        (III)TreeSet:排序、不从负、无索引

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 HashSet<>(); //一行经典代码
        //<String> sets = new LinkedHashSet<>(); //有序 不重复 无索引
        sets.add("Java");
        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);

    }
}

二.HashiSet元素无序的底层原理:哈希表

1HashSet底层原理
(1)HashSet集合底层采取哈希表存储的数据
(2)哈希表是一种对于增删改查数据性能都较好的结构。

2哈希表的组成
(1)JDK8之前,底层使用数组+链表组成
(2)JDK8开始后,底层采用数组+链表+红黑树组成

3哈希值
(1)是JDK根据对象的地址,按照某种规则算出来的int类型的数值

4Object类的API
(1)public int hashCode();

5对象的哈希值特点
(1)同一个对象多次调用hashCode()方法返回的哈希值是相同的
(2)默认情况下,不同对象的哈希值是不同的

6HashSet1.7版本原理解析:数组+链表+(结合哈希算法)
        Set<String> sets = new HashSet<>();

①创建一个默认长度16的数组,数组名table
②根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法)
③判断当前位置是否为null,如果是null直接存入
④如果位置补位null,表示有元素,则调用equals方法比较
⑤如果一样,则不存,如果不一样,则存入数组
        -JDK7新元素占老元素位置,指向老元素
        -JDK8中新元素挂在老元素下面

7结论:哈希表是一种对于增删改查数据性能都较好的结构。

8JDK1.8版本开始HashSet原理解析
(1)底层结构:哈希表(数组、链表、红黑树的结合体)
(2)当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树

9总结
(1)Set集合的底层原理是什么样的
(I)JDK8之前的,哈希表:底层使用数组+链表组成
(II)JDK8开始后,哈希表:底层采用数组+链表+红黑树组成

(2)哈希表的详细流程
(I)创建一个默认长度16,默认加载因为0.75的数组,数组名table
(II)根据元素的哈希值跟数组的长度计算出应存入的位置
(III)判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组        
(IV)当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍

三.HashSet元素去重复的底层原理

案例:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合,要求:学生对象的成员变量值相同,我们就认为是同一个对象

分析:①定义学生类,创建HashSet集合对象,创建学生对象
           ②把学生添加到集合
           ③在学生类中重写两个方法,hashCode()和equals(),自动生成即可
           ④遍历集合(增强for)

总结:1如果希望Set集合认为2个内容相同的对象时重复的应该怎么办?
                重写对象的hashCode和equals方法

package com.itheima_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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }

    /**
     * 只要2个对象一样,结果一定是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);
    }
}
package com.itheima_d1_set;

import java.util.HashSet;
import java.util.Set;

/*
    目标:让Set集合把从夫内容的对象去掉一个(去重复)
 */
public class SetDemo03 {
    public static void main(String[] args) {
        //Set集合去重复原因:先判断哈希值 在判断equals
        Set<Student> sets = new HashSet<>();

        Student s1 = new Student("鲁智深", 18 , '男');
        Student s2 = new Student("匿蝶", 25 , '女');
        Student s3 = new Student("匿蝶", 25 , '女');

        sets.add(s1);
        sets.add(s2);
        sets.add(s3);

        System.out.println(sets);
    }

}
package com.itheima_d1_set;

import java.util.HashSet;
import java.util.Set;

public class SetDemo04 {
    public static void main(String[] args) {
        //看看Set系列集合的特点,HashSet LinkedHashSET TreeSet
        Set<String> sets = new HashSet<>(); //一行经典代码
        //<String> sets = new LinkedHashSet<>(); //有序 不重复 无索引
        sets.add("Java");
        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);

    }
}

四.实现类:LinkedHashSet

1LinkedHashSet集合概述和特点
(1)有序、不重复、无索引
(2)这里的有序指的是保证存储和取出的元素顺序一致   
(3)原理:底层数据结构是依然哈希表,只是每个元素有额外的多了一个双链表的机制记录存储的循序

总结:
1LinkedHashSet集合的特点和原理是怎么样的?
(1)有序、不重复、无索引
(2)底层基于哈希表,使用双链表记录添加顺序

五.实现类:TreeSet

1TreeSet集合概述和特点
(1)不重复、无索引、可排序
(2)可排序:按照元素的大小默认升序(由小到大)排序
(3)TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好
(4)注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序

2TreeSet集合默认的规则
(1)对于数值类型:Interger , Double , 官方默认按照大小进行升序排序
(2)对于字符串类型:默认按照首字符的编号升序排序
(3)对于自定义类型如Student对象,TreeSet无法直接排序

结论:想要使用TreeSet定义类型,需要指定排序规则

3自定义排序规则
(1)TreeSet集合存储对象的时候有2种方式可以设计自定义比较规则
①方式一
(I)让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则

②方式二
(II)TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则

(2)两种方式中,关羽返回值的规则:
(I)如果认为第一个元素大于第二个元素返回正整数即可
(II)如果认为第一个元素小于第二个元素返回负整数即可
(III)如果认为第一个元素等于第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复

(3)注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序2

4总结:

(1)TreeSet集合的特点是怎么样的?
(I)可排序、不重复、无索引
(II)底层基于红黑树实现排序,增删改查性能较好

(2)TreeSet集合自定义排序规则有几种方法
(I)2种
(II)类实现Comparable接口,重写比较规则
(III)集合自定义Comparator比较器对象,重写比较规则

package com.itheima_d1_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 >=0 ? 1 : -1;
    }
}
package com.itheima_d1_set;

import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

/**
 * 目标:观察TreeSet对于有值特性的数据如何排序
 *      学会对自定义类型的对象进行指定规则排序
 */
public class SetDemo05 {
    public static void main(String[] args) {
        Set<Integer> sets = new TreeSet<>();//不重复 无索引 可排序
        sets.add(23);
        sets.add(24);
        sets.add(12);
        sets.add(8);
        System.out.println(sets);

        Set<String> sets1 = new TreeSet<>();//不重复 无索引 可排序
        sets1.add("Java");
        sets1.add("Java");
        sets1.add("About");
        sets1.add("angela");
        sets1.add("Python");
        sets1.add("UI");
        sets1.add("UI");
        sets1.add("黑马");
        System.out.println(sets1);

        System.out.println("=================");
        //方式二:集合自带比较器对象进行规则制定
        Set<Apple> apples = new TreeSet<>((Apple o1 , Apple o2) -> {
            return Double.compare(o2.getPrice() , o1.getPrice());
        });
                /*{
            @Override
            public int compare(Apple o1, Apple o2) {
                //return o1.getWeight() - o2.getWeight();//升序
                //return o2.getWeight() - o1.getWeight();//降序
                //注意:浮点型建议直接使用Double.compare进行比较
                //return Double.compare(o1.getPrice(), o2.getPrice());//升序
                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("黄富士" , "黄色" , 9.8 , 500));
        System.out.println(apples);
    }

}

六.Collection体系的特点、使用场景总结

1如果希望元素可以重复,又有索引,索引查询要快?
(1)用ArrayList集合,基于数组的。(用的最多)

2如果希望元素可以重复,又有索引,增删首尾操作快
(1)用LinkedList集合,基于链表的

3如果希望增删改查都快,但是元素不重复、无序、无索引
(1)用HashSet集合,基于哈希表的

package com.itheima_d2_params;

import java.util.Arrays;

public class MethodDemo {
    public static void main(String[] args) {
        sum();//1不传参数
        sum(10);//2可以传一个参数
        sum(10 , 20 , 30);//3可以传多个参数
        sum(new int[]{10 , 20 , 30 , 40 , 50});//4可以传输一个数组
    }

    /**
     * 注意:一个形参列表只能有一个可变参数,可变参数必须放在形参列表的最后面
     * @param nums
     */
    public static void sum(int...nums){
        //public static void sum(int age , int...nums){}
        //注意:可变参数在方法内部其实就是一个数组。nums
        System.out.println("元素个数:" + nums.length);
        System.out.println("元素内容:" + Arrays.toString(nums));
    }


}

4如果希望增删改查都快,但是元素不重复、有序、无索引
(1)用LinkedHashSet集合,基于哈希表和双链表

5如果要对对象进行排序
(1)用TreeSet集合,基于红黑树。后续也可以用List集合实现排序

补充知识:可变参数:
1可变参数
        (1)可变参数用在形参中可以接收多个数据
        (2)可变参数的格式:数据类型...参数名称

2可变参数的作用
        (1)传输参数非常灵活,方便。可以不传输参数,可以传输1个或者多个,也可以传输一个数组

3可变参数的注意事项
        (1)一个形参列表中可变参数只能有一个
        (2)可变参数必须放在形参列表的最后面

补充知识:集合工具类Collections
1Collections集合工具类
        (1)java.utils.Collections:是集合工具类
        (2)作用:Collections并不属于集合,是用来操作集合的工具类

2Collection常用的API

方法名称说明
public static <T> boolean addAll(Collection<? super T> c, T...elements)给集合对象批量添加元素
public static void shuffle (List<?> list)打乱List集合元素的顺序

3Collection排序相关API
(1)使用范围:只能对于List集合的排序
        ①排序方法1:

方法名称说明
public static <T> void sort(List<T> list)将集合中元素按照默认规则排序        

        注意:本方式不可以直接怼自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable接口

        ②排序方法2

方法名称说明
public static <T> void sort(List<T> list , Comparator<? super T> c)将集合中元素按照指定规则排序
package com.itheima.d3_collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsDemo01 {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        //names.add("楚留香");
        //names.add("胡铁花");
        //names.add("张无忌");
        //names.add("陆小凤");
        Collections.addAll(names , "楚留香" , "胡铁花" , "张无忌" , "陆小凤");
        System.out.println(names);

        //2public static void shuffle(List<?> List) :打乱集合顺序
        Collections.shuffle(names);
        System.out.println(names);

        //3public static void <T> void sort(List<T> list):将集合中元素按照默认规则排序
        List<Integer> list = new ArrayList<>();
        Collections.addAll(list , 12 , 23 , 2 , 4);
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);

    }
}
package com.itheima.d3_collections;

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 >=0 ? 1 : -1;//List中存储相同大小的元素 会保留!
    }
}
package com.itheima.d3_collections;



import java.util.*;

public class CollectionsDemo02 {
    public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>(); //可以重复!
        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("黄富士" , "黄色" , 9.8 , 500));
        /*Collections.sort(apples);//可以的,Apple类已经重写了比较规则
        System.out.println(apples);*/

        //方式二:sort方法自带比较器对象
        /*Collections.sort(apples, new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return Double.compare(o1.getPrice(), o2.getPrice());
            }
        });*/
        Collections.sort(apples, ( o1,  o2) ->{ return Double.compare(o1.getPrice(), o2.getPrice());});
        System.out.println(apples);
    }
}

Collection体系的综合案例

斗地主游戏:
        需求:在启动游戏房间的时候,应该提前准备好54张牌,完成洗牌、发牌、牌排序、逻辑

        分析:①当系统启动的同时需要准备好数据的时候,就可以用静态代码块
                   ②洗牌就是打乱牌的顺序
                   ③定义三个玩家、以此发出51张牌
                   ④给玩家的牌进行排序(扩展)
                   ⑤输出每个玩家的牌数据

package com.itheima.d4_collection_test;

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 size + color;
    }


}
package com.itheima.d4_collection_test;

import com.sun.source.tree.Tree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class GameDemo {
    /**
     *1定义一个静态的集合存储54张牌对象
     */
    public static List<Card> allCard = 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存入到集合容器中去
                allCard.add(c);
            }
        }
        //8大小王存入集合中去
        Card c1 = new Card("" , "小王" , ++index);
        Card c2 = new Card("" , "大王" , ++index);
        Collections.addAll(allCard , c1 , c2);
        System.out.println("新牌:" + allCard);
    }

    public static void main(String[] args) {
        //9洗牌
        Collections.shuffle(allCard);
        System.out.println("洗牌后:" + allCard);

        //10发牌(定义三个玩家,每个玩家的牌也是一个集合容器)
        List<Card> linhuchong = new ArrayList<>();
        List<Card> jiumozhi = new ArrayList<>();
        List<Card> renyingying = new ArrayList<>();

        //11开始发牌(从牌集合中发出51张牌给三个玩家,剩余三张作为底牌)
        //allCards = [8♣, 3♣, 9♠, Q♦, 4♥, 9♣, Q♠, 2♠, A♠]
        for (int i = 0; i < allCard.size() - 3; i++) {
            //先拿到当前牌对象
            Card c = allCard.get(i);
            if (i % 3 ==0){
                //请阿冲接牌
                linhuchong.add(c);
            }else if (i % 3 == 1){
                //请阿玖
                jiumozhi.add(c);
            }else if (i % 3 == 2){
                //请盈盈接牌
                renyingying.add(c);
            }
        }

        //12最后三张底牌(把最后三张牌截取成一个子集合)
        List<Card> lastThreeCards = allCard.subList(allCard.size() - 3 , allCard.size());

        //13给玩家的牌排序(从大到小 )
        sortCards(linhuchong);
        sortCards(jiumozhi);
        sortCards(renyingying);

        //14输出玩家的牌
        System.out.println("阿冲:" + linhuchong);
        System.out.println("阿玖:" + jiumozhi);
        System.out.println("盈盈:" + renyingying);
        System.out.println("三张底牌:" + lastThreeCards);
    }

    /**
     * 给牌排序
     * @param cards
     */
    private static void sortCards(List<Card> cards) {
        //[K♥, A♥, Q♠, 10♥, J♣, Q♦
        Collections.sort(cards, (Card o1, Card o2) -> {return o2.getIndex() - o1.getIndex();});
                //o1 = K♥
                //o2 = A♥
                //知道牌的大小,才可以制定规则



    }
}

Map集合体系

一.Map集合的概述

1Map集合概述和使用
(1)Map集合是一种双列集合,每个元素包含两个数据
(2)Map集合的每个元素的格式:key=value(键值对元素)
(3)Map集合也被称为“键值对集合”

2Map集合整体格式
(1)Collection集合的格式:[元素1 , 元素2 , 元素3]
(2)Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3, ...}

3Map集合的使用场景之一:购物车系统
  分析
(1)购物车提供的四个商品
(2)每个商品对象都一一对应一个购买数量
(3)把商品对象看成是Map集合的建,购买数量看成Map集合的值
{商品1=2 ,商品2=3 ,商品3=2 ,商品4=3}

4总结:

(1)Map集合是什么?使用场景是什么样的?
(I)Map集合是键值对集合
(II)Map集合非常适合做类购物车这样的业务场景

二.Map集合体系特点

1Map集合体系

 2Map集合体系特点
(1)Map集合的特点都是由键决定的
(2)Map集合的键是无序的,不重复的,无索引的,值不做要求(可以重复)
(3)Map集合的键对应的值会覆盖前面重复键的值
(4)Map集合的键值对都可以为null

3Map集合实现类特点
(1)HashMap:元素按照键是无序,不重复,无索引,值不做要求。(与Map体系一致)
(2)LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求
(3)TreeMap:元素按照键是排序,不重复,无索引,值不作要求

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) {
        //1创建一个Map集合对象
        Map<String , Integer> maps = new LinkedHashMap<>();//一行经典代码
        maps.put("鸿星尔克" , 3);
        maps.put("枸杞" , 100);
        maps.put("Java" , 1);
        maps.put("Java" , 100);
        maps.put(null , null);
        System.out.println(maps);
    }
}

三.Map集合常用API

1Map集合
(1)Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的。

2Map API如下:

方法名称说明
V put(K key , V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数
package com.itheima.d6_map_traversal;

import java.util.*;

public class MapDemo {
    public static void main(String[] args) {
        //1添加元素:无序,不重复,无索引
        Map<String , Integer> maps = new HashMap<>();
        maps.put("iphoneX" , 10);
        maps.put("娃娃" , 20);
        maps.put("iphoneX" , 100);
        maps.put("huawei" , 1000);
        maps.put("生活用品" , 10);
        maps.put("手表" , 10);
        //{huawei=1000, 手表=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("华为");
        System.out.println(Key);
        System.out.println(maps.get("生活用品"));//10
        System.out.println(maps.get("生活用品2"));

        //5根据键删除整个元素(删除键会返回键的值)
        System.out.println(maps.remove("iphoneX"));
        System.out.println(maps);

        //6判断是否包含某个键,包含返回true,反之
        System.out.println(maps.containsKey("娃娃"));// true
        System.out.println(maps.containsKey("iphoneX")); //false

        //7判断是否包含某个值
        System.out.println(maps.containsValue(1000));
        System.out.println(maps.containsValue(10));
        System.out.println(maps.containsValue(22));

        //{huawei=1000, 手表=10, 生活用品=10, 娃娃=20}
        //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);
        Map<String , Integer> map2 = new HashMap<>();
        map2.put("java2" , 1);
        map2.put("java3" , 100);
        map1.putAll(map2);//把map2的元素拷贝一份到map1中去
        System.out.println(map1);
        System.out.println(map2);
    }
}

四.Map集合的遍历方式一:键找值

1Map集合方式一:键找值流程
(1)先获取Map集合的全部键的Set集合
(2)遍历的Set集合,然后通过键提取对应值

2键找值涉及到的API:

方法名称说明
Set<K> keySet()获取所有键的集合
V get(Object key)根据键获取值

五.Map集合的遍历方式二:键值对

1遍历Map集合方式二:键值对流程
(1)先把Map集合转换成Set集合,Set集合中每个元素都是键值对实体类型了
(2)遍历Set集合,然后提取键以及提取值

2键值对涉及的API:

方法名称说明
Set <Map.Entry<K , v>> entrySet()获取所有键值对对象的集合
K getKey()获取键
V getValue()获取值
package com.itheima.d7_map_traversal;

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<>();
        //1添加元素:无序,不重复,无索引
        maps.put("娃娃", 30);
        maps.put("iphoneX" , 100);
        maps.put("huawei" , 1000);
        maps.put("生活用品" , 10);
        maps.put("手表" , 10);

        //2把Map集合转换成Set集合
        Set<Map.Entry<String, Integer>> entries = maps.entrySet();
        //3开始遍历
        Set<Map.Entry<String, Integer>> entries1 = entries;
        for (Map.Entry<String, Integer> entry : entries) {
            String key = entry.getKey();
            int value = entry.getValue();
            System.out.println(key + "========>" + value);
        }
    }
}

六.Map集合的遍历方式三:lambda表达式

1Map集合的遍历方式三:Lambda
(1)得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式

2Map结合Lambda遍历的API

方法名称说明
default void forEach(BiConsumer<? super K, ? super V> action)结合lambda遍历Map集合

流程:
        maps = {huawei=1000 , 手表=10 , 生活用品 , iphoneX=100}

map.forEach((k , v) -> {
        System.out.println(k + "------>"  + V);
});

package com.itheima.d7_map_traversal;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class MapDemo03 {
    public static void main(String[] args) {
        Map<String , Integer> maps = new HashMap<>();
        //1添加元素:无序,不重复,无索引
        maps.put("娃娃", 30);
        maps.put("iphoneX" , 100);
        maps.put("huawei" , 1000);
        maps.put("生活用品" , 10);
        maps.put("手表" , 10);
        System.out.println(maps);

        //maps = {huawei=1000, 手表=10, 生活用品=10, iphoneX=100, 娃娃=30}

        maps.forEach((k,  v) ->{
                System.out.println(k + "--->" + v);

        });
    }
}

七.案例:Map集合案例-统计投票人数
        需求:某个班80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A  、V 、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多

        分析:将80个学生选择的数据拿到程序中去
                   定义Map集合用于存储最终统计的结果
                   遍历80个学生选择的数据,看Map集合中是否存在,不存在存入“数据=1”,存在则其对应值+1

package com.itheima.d8_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 sb = new StringBuilder();
        Random r = new Random();
        for (int i = 0; i < 80; i++) {
            sb.append(selects[r.nextInt(selects.length)]);
        }
        System.out.println(sb);

        //2定义一个Map集合记录最终统计的结果:A=30 B=20 C=20 D=10    键是景点,值是选择的数量
        Map<Character , Integer> infos = new HashMap<>();//{}

        //3遍历80个学生选择的数据
        for (int i = 0; i < sb.length(); i++) {
            //4提取当前选择景点字符
            char ch = sb.charAt(i);
            //5判断Map集合中是否存在这个键
            if (infos.containsKey(ch)){
                //让其值 + 1
                infos.put(ch , infos.get(ch) + 1);
            }else{
                //说明此景点是第一次被选
                infos.put(ch , 1);
            }
        }
        //6输出集合
        System.out.println(infos);
    }
}

八.Map集合的实现类HashMap

1HashMap的特点
(1)HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
(2)没有额外需要学习的特有方法,直接使用Map里面的方法就可以了
(3)HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已

2实际上:Set系列集合的底层就是Map实现的,只是Set集合中的元素只要键数据,不要值数据而已
public HashSet(){
        map = new HashMap<>();
}

3总结:
(1)HashMap的特点和底层原理
        (I)由键决定:无序、不重复、无索引。HashMap底层是1哈希表结构的。
        (II)以来hashCode方法和equals方法保证键的唯一
        (III)如果键要存储的是自定义对象,需要重写hashCode和equals方法
        (IV)基于哈希表。增删改查性能都较好

package com.itheima.d9_map_impl;

import com.itheima.d1_set.Student;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class HashMapDemo1 {
    public static void main(String[] args) {
        //Map集合是根据键去重复元素
        Map<Student , String> maps = new HashMap<>();

        Student s1 = new Student("鲁智深", 18 , '男');
        Student s2 = new Student("匿蝶", 25 , '女');
        Student s3 = new Student("匿蝶", 25 , '女');

        maps.put(s1 , "北京");
        maps.put(s2 , "上海");
        maps.put(s3 , "广州");
        System.out.println(maps);

    }
}

九.Map集合的实现类LinkedHashMap

1LinkedHashMap集合概述和特点
(1)由键决定:有序、不重复、无索引
(2)这里的有序指的是保证存储和取出的顺序一致
(3)原理:底层数据结构依然是哈希表,只每个键值对元素又额外的多了一个双链表的机制记录存储的顺序

package com.itheima.d9_map_impl;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeSet;

/**
 * 认识Map体系的特点:按照键无序,不重复,无索引,值不做要求
 */
public class LinkedHashDemo2 {
    public static void main(String[] args) {
        //1创建一个Map集合对象
        Map<String , Integer> maps = new LinkedHashMap<>();//一行经典代码
        maps.put("鸿星尔克" , 3);
        maps.put("枸杞" , 100);
        maps.put("Java" , 1);
        maps.put("Java" , 100);
        maps.put(null , null);
        System.out.println(maps);


    }
}

十.TreeMap集合概述和特点

1TreeMap集合概述和特点
(1)由键决定特性:不重复、无索引、可排序
(2)可排序:按照数据的大小默认升序(由小到大)排序。只能对键排序。
(3)注意:TreeMap集合是一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序
(4)TreeMap个TreeSet一样底层原理是一样的。

2TreeMap集合自定义排序规则有两种
(1)类实现Comparable接口,重写比较规则
(2)集合自定义Comparator比较器对象,重写比较规则

package com.itheima.d9_map_impl;

import com.itheima.d1_set.Apple;

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapDemo3 {
    public static void main(String[] args) {
        Map<Integer , String> map1 = new TreeMap<>();
        map1.put(13,"王麻子");
        map1.put(1,"张三");
        map1.put(3,"县长");
        System.out.println(map1);
        //TreeMap集合自带排序。 可排序 , 不重复(只要大小规则一样就默认重复) 无索引
        Map<Apple , String> maps = new TreeMap<>(new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return Double.compare(o2.getPrice(), o1.getPrice());//按照价格降序排序
            }
        });
        maps.put(new Apple("红富士" , "红色" , 9.9 , 500) , "山东");
        maps.put(new Apple("青苹果" , "绿色" , 15.9 , 300) , "上海");
        maps.put(new Apple("绿富士" , "青色" , 29.9 , 400) , "八宝山");
        maps.put(new Apple("黄富士" , "黄色" , 9.8 , 500) , "湖北");

        System.out.println(maps);
    }
}

补充知识:集合的嵌套
案例:Map集合阿里-统计投票人数
需求:某个班级多名学生,现在需要组成秋游活动,班长提供了四个景点一次是(A  、B、C、D),每个学生可以选择多个景点,请统计出哪个景点想去的人数最多
分析:①将80个学生选择数据拿到程序中去,需要记住每个学生选择的情况。
           ②定义Map集合用于存储最终统计的结果

package com.itheima.d9_map_impl;

import java.util.*;

/**
 * 需求:统计投票人数
 */
public class MapTest4 {
    public static void main(String[] args) {
        //1要求程序记录每个学生选择的情况
        //使用一个Map集合存储
        Map<String , List<String>> data = new HashMap<>();

        //2把学生选择的数据存入进去
        List<String> selects = new ArrayList<>();
        Collections.addAll(selects, "A" , "C");
        data.put("罗勇" , selects);
        System.out.println(data);

        List<String> selects1 = new ArrayList<>();
        Collections.addAll(selects1 , "A" , "B", "C");
        data.put("胡桃" , selects1);
        System.out.println(data);

        List<String> selects2 = new ArrayList<>();
        Collections.addAll(selects2 , "A" , "B", "C" , "D");
        data.put("刘军" , selects2);
        System.out.println(data);

        //3统计每个景点选择的人数
        Map<String , Integer> infos = new HashMap<>();

        //4提取所有人选择的景点的信息
        Collection<List<String>> values = data.values();
        System.out.println(values);
        //value = {[A , B , C , D] , [B , C , D] , [ A , C ]}

        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);
        

    }
}

教学视频资源来自

Java入门基础视频教程,java零基础自学首选黑马程序员Java入门教程(含Java项目和Java真题)_哔哩哔哩_bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值