JAVA_HashSet-TreeMap-HashMap-Map

红黑树:特殊的二叉查找树,通过自己的红黑规则实现

红黑规则:

HashSet:

特点:1.底层数据结构是哈希表

2.不能保证存储和取出的顺序完全一致

3.没有带索引的方法,所以不能使用普通for循环遍历

4.由于是set集合,所以元素唯一

例子:

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo1 {
    
    
    public static void main(String[] args) {
    
    
        HashSet<String> hs = new HashSet<>();

        hs.add("hello");
        hs.add("world");
        hs.add("java");
        hs.add("java");
        hs.add("java");

        Iterator<String> it = hs.iterator();
        while (it.hasNext()){
    
    
            String s = it.next();
            System.out.println(s);
        }

        System.out.println("---------------");
        for (String h : hs) {
    
    

            System.out.println(h);
        }
    }
}

结果:
world
java
hello
---------------
world
java
hello

哈希值:

是根据对象的地址或者属性值,算出来的int类型的整数

Object类中有一个方法可以获取对象的哈希值

public int hashCode():根据对象的地址计算出来的哈希值

对象的哈希值特点:

如果没有重写hashCode方法,那么是根据对象的地址值计算出的哈希值.

同一个对象多次调用hashCode()方法返回的哈希值是相同的

不同对象的哈希值是不一样的

如果重写了hashCode方法,一般是通过对象的属性值计算出哈希值

例子:

public class Student {
    
    
    private String name;
    private int age;

    public Student() {
    
    
    }

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }
    //我们可以对Object类中的hashCode方法进行重写
    //在重写之后,就一般是根据对象的属性值来计算哈希值的
    //此时跟对象的地址值是没有关系的
    @Override
    public int hashCode() {
    
    
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
/*
创建对象 计算哈希值
 */
public class HashSetDemo2 {
    
    
    public static void main(String[] args) {
    
    
        Student s1 = new Student("xiaozhi",21);
        Student s2 = new Student("xiaomei",22);

        //因为在Object类中,是根据对象的地址值计算出来的哈希值
        System.out.println(s1.hashCode());//189568618
        System.out.println(s1.hashCode());//189568618

        System.out.println(s2.hashCode());//793589513

    }
}

常见数据结构之哈希表:

哈希表:

JDK8之前,底层采用数组+链表实现.

JDK8之后,底层进行了优化.由数组+链表+红黑树 实现.

LinkedHashSet:元素,有序的,按添加的顺序

Collextion:

List:有序,有索引,元素可以重复

​ ArrayList:底层是数组结构,所以查询快,增删慢

​ LinkedList:底层是链表结构,所以查询慢,增删块

Set:无序,无索引,元素不可以重复

​ TreeSet:

​ 要求:实现Comparable接口,或者指定一个Comparator比较器对象

​ 元素会自然排序

​ HashSet:

​ 要求,重写hashCode和equals方法

在不同的场景下,可以使用不同的集合.

​ 允不允许重复:

​ 允许重复:

​ 查询多:ArrayList

​ 增删多:LinkedList

不知道:ArrayList

​ 不允许:

​ 要求元素有序:LinkedHashSet

​ 要求元素有顺序:TreeSet

​ 不知道:HashSet(常用的)

set:无序,无索引,不可以重复

HashSet:

底层:哈希表 重写hashCode和equals方法

如果你不重写这些方法:

1.不能去掉重复

2.remove, contains 方法不管用

TreeSet:

底层:红黑树 必须给定排序规则

Map:

单列集合:每次只添加一个元素

双列集合:一次可以添加一对数据

map集合是个接口:

Interface Map<K,V> K:键的数据类型 V:值的数据类型

键不能重复,值可以重复

键和值是一一对应的,每个键只能找到自己对应的值

(键+值)这个整体 我们称之为"键值对" 或者"键值对对象" ,在Java中叫做"Entry对象"

无序

键 值 每个键对应一个值 键值对

例子:

public class MyMap1 {
    
    
    public static void main(String[] args) {
    
    
        Map<String,String> map = new HashMap<>();

        //put
        map.put("itheima001","小智");
        map.put("itheima002","小美");
        map.put("itheima003","小胖");

        System.out.println(map);
        //{itheima003=小胖, itheima001=小智, itheima002=小美}
    }
}

Map的常用方法:

方法名 说明
V put(K key,V value) 添加元素
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数
public class MyMap2 {
    
    
    public static void main(String[] args) {
    
    
        Map<String,String> map = new HashMap<>();
        //V   put(K key,V   value)  添加元素
        map.put("itheima001","王芳");
        map.put("itheima002","小智");

        //method1(map);
        //method2(map);
        //method3(map);
        //method4(map);
        //method5(map);
        //method6(map);
        method7(map);


    }

    private static void method7(Map<String, String> map) {
    
    
        //        int size()集合的长度,也就是集合中键值对
        int size = map.size();
        System.out.println(size);//2
    }

    private static void method6(Map<String, String> map) {
    
    
        //        boolean isEmpty()判断集合是否为空
        boolean empty = map.isEmpty();
        System.out.println(empty);
    }

    private static void method5(Map<String, String> map) {
    
    
        //        boolean containsValue(Object value)判断集合是否包含指定的值
        boolean b1 = map.containsValue("王强");
        System.out.println(b1);//false
    }

    private static void method4(Map<String, String> map) {
    
    
        //        boolean containsKey(Object key) 判断集合是否包含指定的键
        boolean b = map.containsKey("itheima001");
        System.out.println(b);//true
    }

    private static void method3(Map<String, String> map) {
    
    
        //        void   clear() 移除所有的键值对元素
        map.clear();
        System.out.println(map);
    }

    private static void method2(Map<String, String> map) {
    
    
        //V   remove(Object key)根据键删除键值对元素
        String s = map.remove("itheima001");
        System.out.println(s);//王芳
        System.out.println(map);//{itheima002=小智}
    }

    private static void method1(Map<String, String> map) {
    
    
        //如果添加的键不存在,那么会把键值对都添加到集合中
        //如果要添加的键是存在的,那么会覆盖原先的值,把原先值当做返回值进行返回
        String s = map.put("itheima001", "aaa");
        System.out.println(s);//王芳
        System.out.println(map);//{itheima001=aaa, itheima002=小智}
    }

}

Map集合的获取功能【应用】

  • 方法介绍

    方法名 说明
    V get(Object key) 根据键获取值
    Set keySet() 获取所有键的集合
    Collection values() 获取所有值的集合
    Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合

Map集合的遍历(方式1)【应用】

  • 遍历思路

    • 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
      • 把所有的丈夫给集中起来
      • 遍历丈夫的集合,获取到每一个丈夫
      • 根据丈夫去找对应的妻子
  • 步骤分析

    • 获取所有键的集合。用keySet()方法实现
    • 遍历键的集合,获取到每一个键。用增强for实现
    • 根据键去找值。用get(Object key)方法实现
public class MyMap3 {
    
    
    public static void main(String[] args) {
    
    
        //创建集合添加元素
        Map<String,String> map = new HashMap<>();
        map.put("1号丈夫","1号妻子");
        map.put("2号丈夫","2号妻子");
        map.put("3号丈夫","3号妻子");
        map.put("4号丈夫","4号妻子");
        //获取到所有的键
        Set<String> keys = map.keySet();
        //遍历set集合得到每一个键
        for (String key : keys) {
    
    
            String value = map.get(key);
            System.out.println(key + "------" + value);
        }
       /* 1号丈夫------1号妻子
        2号丈夫------2号妻子
        4号丈夫------4号妻子
        3号丈夫------3号妻子*/

    }
}

Map集合的遍历(方式2)【应用】

  • 遍历思路

    • 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
      • 获取所有结婚证的集合
      • 遍历结婚证的集合,得到每一个结婚证
      • 根据结婚证获取丈夫和妻子
  • 步骤分析

    • 获取所有键值对对象的集合
      • Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
    • 遍历键值对对象的集合,得到每一个键值对对象
      • 用增强for实现,得到每一个Map.Entry
    • 根据键值对对象获取键和值
      • 用getKey()得到键
      • 用getValue()得到值
public class MyMap4 {
    
    
    public static void main(String[] args) {
    
    
        //创建集合添加元素
        Map<String,String> map = new HashMap<>();
        map.put("1号丈夫","1号妻子");
        map.put("2号丈夫","2号妻子");
        map.put("3号丈夫","3号妻子");
        map.put("4号丈夫","4号妻子");
        //获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //遍历键值对集合对象
        for (Map.Entry<String, String> entry : entries) {
    
    
            //getKey()得到键
            String key = entry.getKey();
            //getValue()得到值
            String value = entry.getValue();
            System.out.println(key + "------" +value);
        }
        /*1号丈夫------1号妻子
        2号丈夫------2号妻子
        4号丈夫------4号妻子
        3号丈夫------3号妻子*/
    }
}

HashMap集合

4.1HashMap集合概述和特点【理解】

  • HashMap底层是哈希表结构的
  • 依赖hashCode方法和equals方法保证键的唯一
  • 如果键要存储的是自定义对象,需要重写hashCode和equals方法

4.2HashMap集合应用案例【应用】

  • 案例需求

    • 创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
    • 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
public class StudentMap {
    
    
    public static void main(String[] args) {
    
    
        HashMap<Student,String> map = new HashMap<>();

        //创建学生对象
        Student s1 = new Student("小红",19);
        Student s2 = new Student("小蓝",18);
        Student s3 = new Student("小白",20);

        //添加到集合
        map.put(s1,"北京");
        map.put(s2,"上海");
        map.put(s3,"郑州");

        /*//第一种
        Set<Student> keys = map.keySet();
        for (Student key : keys) {
            String value = map.get(key);
            System.out.println(key + "---------" + value);
        }*/
        /*//第二种
        //获取键值对
        Set<Map.Entry<Student, String>> entries = map.entrySet();
        //遍历
        for (Map.Entry<Student, String> entry : entries) {
            //获取键
            Student key = entry.getKey();
            //获取值
            String value = entry.getValue();
            System.out.println(key + "---------" + value);
        }*/

        //第三种
        map.forEach(
                (Student key, String value) ->{
    
    
                   System.out.println(key + "---------" + value);
                }
        );
        /*Student{name='小白', age=20}---------郑州
        Student{name='小红', age=19}---------北京
        Student{name='小蓝', age=18}---------上海*/
    }
}

HashMap的键 就是HashSet

TreeMap 键就是TreeSet

TreeMap集合

5.1TreeMap集合概述和特点【理解】

  • TreeMap底层是红黑树结构
  • 依赖自然排序或者比较器排序,对键进行排序
  • 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则

5.2TreeMap集合应用案例【应用】

  • 案例需求

    • 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
    • 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
  • 代码实现

public class Student /*implements Comparable<Student> */{
    
    
    private String name;
    private int age;

    public Student() {
    
    
    }

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
    
    
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

   /* @Override
    public int compareTo(Student o) {
        //按年龄
        int result = this.getAge() - o.getAge();
        //次要 姓名
        result = result == 0 ? this.getName().compareTo(o.getName()) : result;
        return result;
    }*/
}
public class StudentTest {
    
    
    public static void main(String[] args) {
    
    
        TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
    
    
            @Override
            public int compare(Student o1, Student o2) {
    
    
                int result = o1.getAge() - o2.getAge();
                result = result == 0 ? o1.getName().compareTo(o2.getName()) : result;
                return result;
            }
        });

        Student s1 = new Student("xiaomei",29);
        Student s2 = new Student("zhangsan",23);
        Student s3 = new Student("lisi",29);

        tm.put(s1,"上海");
        tm.put(s2,"北京");
        tm.put(s3,"江苏");

        tm.forEach(
                (Student key,String value)->{
    
    
                    System.out.println(key +"--------"+ value);
                }
        );
        /*Student{name='zhangsan', age=23}--------北京
        Student{name='lisi', age=29}--------江苏
        Student{name='xiaomei', age=29}--------上海*/
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42073385/article/details/108310659