4

红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map...

 3 years ago
source link: http://www.cnblogs.com/859630097com/p/14193135.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

==学习目标==

1、能够了解红黑树

2、能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构)

3、能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历)

4、能够掌握HashMap集合的特点以及使用

5、能够掌握TreeMap集合的特点以及使用

==知识点==

  1. 红黑树

  2. HashSet

  3. Map

  4. HashMap

  5. TreeMap

==知识点梳理==

ymemyqM.png!mobile

==超详细讲义==

1.红黑树

1.1红黑树-概述【了解】

1.什么是红黑树

平衡二叉B树,每一个节点可以是红或者黑,红黑树不是 高度平衡 的,它的平衡是通过"自己的红黑规则"进行实现的。

3mIfaum.png!mobile

1.2 红黑树-红黑规则 (了解) 

  • 红黑树的红黑规则有哪些

    1. 每一个节点或是红色的,或者是黑色的

    2. 根节点必须是黑色

    3. 所有叶子节点(空的节点被称作叶子节点)都是黑色的

    4. 不能出现两个红色节点相连 的情况

    5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

      uqIv6bJ.png!mobile

1.3 红黑树-添加节点的默认颜色(了解) 

添加节点时,默认为红色,效率高

1.4 红黑树-添加节点后,如何保证红黑规则1 【难点】

3iqEFnM.png!mobile

2qMvYrz.png!mobile

1.5 红黑树-添加节点后,如何保证红黑规则2 【难点】

(旋转之后,根据规则验证是否是红黑树,总结红黑树添加节点的规则)

V7riY3I.png!mobile

zmam63b.png!mobile

1.6 红黑树练习-成绩排序案例【重点】

(共3点)

1.案例需求

  • 用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩,英语成绩),并遍历该集合

  • 要求: 按照总分从低到高排序

代码实现

学生类

public class Student implements Comparable<Student> {
    private String name;
    private int chinese;
    private int math;
    private int english;
​
    public Student() {
    }
​
    public Student(String name, int chinese, int math, int english) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getChinese() {
        return chinese;
    }
​
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }
​
    public int getMath() {
        return math;
    }
​
    public void setMath(int math) {
        this.math = math;
    }
​
    public int getEnglish() {
        return english;
    }
​
    public void setEnglish(int english) {
        this.english = english;
    }
​
    public int getSum() {
        return this.chinese + this.math + this.english;
    }
​
    @Override
    public int compareTo(Student o) {
        // 主要条件: 按照总分进行排序
        int result = o.getSum() - this.getSum();
        // 次要条件: 如果总分一样,就按照语文成绩排序
        result = result == 0 ? o.getChinese() - this.getChinese() : result;
        // 如果语文成绩也一样,就按照数学成绩排序
        result = result == 0 ? o.getMath() - this.getMath() : result;
        // 如果总分一样,各科成绩也都一样,就按照姓名排序
        result = result == 0 ? o.getName().compareTo(this.getName()) : result;
        return result;
    }
}

测试类

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建TreeSet集合对象,通过比较器排序进行排序
        TreeSet<Student> ts = new TreeSet<Student>();
        //创建学生对象
        Student s1 = new Student("jack", 98, 100, 95);
        Student s2 = new Student("rose", 95, 95, 95);
        Student s3 = new Student("sam", 100, 93, 98);
        //把学生对象添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
​
        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getEnglish() + "," + s.getSum());
        }
    }
}

2.TreeSet原理

Bzi2QfY.png!mobile

Zrq6FvQ.png!mobile

2.HashSet集合

2.1HashSet-基本使用【重点】

1.什么是HashSet(HashSet的特点)

  • 底层数据结构是哈希表

  • 存取无序

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历(get方法)

2.HashSet使用-存储字符串并遍历

package com.itheima.myhashset;
​
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");
        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 s : hs) {
            System.out.println(s);
        }
    }
}

2.2哈希值【了解】

1.什么是哈希值

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

2.如何获取对象中的Hash值

Object类中有一个方法: public int hashCode():根据对象的地址值计算出来的哈希值

3.哈希值的特点

  • 没有重写HashCode的情况:

1.同种一对象多次调用hashCode方法返回值是一样的

2.不同对象hashCode方法返回值不一样

  • Object子类重写hashCode方法的情况:

重写的目的是计算对象哈希值时,按属性值来计算,因此只要属性值相同,不同对象的hashCode方法返回值是一样的

package com.itheima.myhashset;
​
/**
 * 计算哈希值
 */
public class HashSetDemo2 {
    public static void main(String[] args) {
        Student s1 = new Student("xiaozhi",23);
        Student s2 = new Student("xiaomei",22);
​
        //因为在Object类中,是根据对象的地址值计算出来的哈希值。
        System.out.println(s1.hashCode());//1060830840
        System.out.println(s1.hashCode());//1060830840
​
​
        System.out.println(s2.hashCode());//2137211482
    }
}

Student类

package com.itheima.myhashset;
​
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;
    }
​
    //我们可以对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 +
                '}';
    }
}

2.4HashSet-JDK7底层原理【难点】

哈希表=数组 + 链表

Ybe6vqE.png!mobile

2.5HashSet-JDK8底层优化【难点】

(共两点)

1.HashSet 在JDK1.8之后的原理

  • 节点个数少于等于8个

    数组 + 链表

  • 节点个数多于8个

    数组 + 红黑树

Az6F7jQ.png!mobile

2.HashSet 在JDK1.8版本的存储流程

MZ777zM.png!mobile

2.6HashSet集合存储学生对象并遍历【重点】

  • 案例需求

    • 创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合

    • 要求:学生对象的成员变量值相同,我们就认为是同一个对象

  • 代码实现

    测试类

    public class HashSetDemo2 {
        public static void main(String[] args) {
            //HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法
            HashSet<Student> hashSet = new HashSet<>();
            Student s1 = new Student("xiaohei",23);
            Student s2 = new Student("xiaohei",23);
            Student s3 = new Student("xiaomei",22);
            hashSet.add(s1);
            hashSet.add(s2);
            hashSet.add(s3);
            for (Student student : hashSet) {
                System.out.println(student);
            }
        }
    }

    学生类

    package com.itheima.myhashset;
    ​
    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 +
                    '}';
        }
    }

3.Map集合

3.1Map-基本使用【重点、难点】

(共3点)

1.什么是Map集合【记忆】

Map集合又称为双列集合,双列集合中元素的内容是成对的

2.Map集合的特点 【记忆】

键不能重复,值可以重复

键与值之间是一一对应的关系

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

yemyYfj.png!mobile

3.如何使用Map集合

1.Map集合格式

interface Map<K,V>  K:键的类型;V:值的类型

2.如何创建Map集合对象

Map<String,String> map = new HashMap<String,String>();//使用具体实现类,采用多态形式创建

4.使用Map集合存储学生学号和姓名

package com.itheima.mapdemo1;
​
import java.util.HashMap;
import java.util.Map;
​
/**
 * Map的基本使用
 */
public class MyMap1 {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
​
        //map.add();
        map.put("itheima001","小智");
        map.put("itheima002","小美");
        map.put("itheima003","大胖");
​
        System.out.println(map);
    }
}

3.2Map常用方法【重点】

  • 方法介绍

    方法名 说明 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.mapdemo1;
    ​
    import java.util.HashMap;
    import java.util.Map;
    /**
     * Map的基本方法
     */
    public class MyMap2 {
        public static void main(String[] args) {
          Map<String,String> map = new HashMap<>();
            map.put("itheima001","小智");
            map.put("itheima002","小美");
            map.put("itheima003","大胖");
          map.put("itheima004","小黑");
            map.put("itheima005","大师");
    ​
          //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);
        }
    ​
        private static void method6(Map<String, String> map) {
            //        boolean isEmpty()       判断集合是否为空
            boolean empty1 = map.isEmpty();
            System.out.println(empty1);//false
    ​
            map.clear();
            boolean empty2 = map.isEmpty();
            System.out.println(empty2);//true
        }
    ​
        private static void method5(Map<String, String> map) {
            //        boolean containsValue(Object value) 判断集合是否包含指定的值
            boolean result1 = map.containsValue("aaa");
            boolean result2 = map.containsValue("小智");
            System.out.println(result1);
            System.out.println(result2);
        }
    ​
        private static void method4(Map<String, String> map) {
            //        boolean containsKey(Object key) 判断集合是否包含指定的键
            boolean result1 = map.containsKey("itheima001");
            boolean result2 = map.containsKey("itheima006");
            System.out.println(result1);
            System.out.println(result2);
        }
    ​
        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);
        }
    ​
        private static void method1(Map<String, String> map) {
            //        V put(K key,V value)    添加元素
            //如果要添加的键不存在,那么会把键值对都添加到集合中
            //如果要添加的键是存在的,那么会覆盖原先的值,把原先值当做返回值进行返回。
            String s = map.put("itheima001", "aaa");
            System.out.println(s);
            System.out.println(map);
        }
    }

3.3Map-第一种遍历方式【重点】

方法介绍

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

AJfIzq3.png!mobile

示例代码

package com.itheima.mapdemo1;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
 * Map的第一种遍历方式
 */
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号妻子");
        map.put("5号丈夫","5号妻子");
​
        //获取到所有的键
      Set<String> keys = map.keySet();
        //遍历Set集合得到每一个键
        for (String key : keys) {
            //通过每一个键key,来获取到对应的值
            String value = map.get(key);
            System.out.println(key + "---" + value);
        }
    }
}

3.4Map-第二种遍历方式【重点】

方法介绍

方法名 说明 Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象集合 K getKey() 获得键值 V getValue() 获得值

maMFvyN.png!mobile

ZjmaqaV.jpg!mobile

示例代码

package com.itheima.mapdemo1;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
​
/**
 * Map的第二种遍历方式
 */
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号妻子");
        map.put("5号丈夫","5号妻子");
​
        //首先要获取到所有的键值对对象。
        //Set集合中装的是键值对对象(Entry对象)
        //而Entry里面装的是键和值
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            //得到每一个键值对对象
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "---" + value);
        }
    }
}

4.HashMap集合

4.1HashMap-原理解析【难点】

1.HashMap小结

  • HashMap底层是哈希表结构

  • 依赖hashCode方法和equals方法保证键的唯一

  • 如果键要存储自定义对象,需要重写hashCode和equals方法

QJ7FZr.png!mobile

4.2 HashMap集合-练习【重点】

(共4点,第4点是对forEache的解析)

1.案例需求

  • 创建一个HashMap集合,键是学生对象(Student),值是籍贯 (String)。存储三个元素,并遍历。

  • 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象

2.实现思路

  • 定义学生类

  • 创建HashMap集合对象

  • 添加学生对象

  • 为了保证key的一致性,重写学生类的hashCode和equals方法

3.代码实现

学生类

package com.itheima.mapdemo1;
​
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;
    }
​
    @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 +
                '}';
    }
}

测试类

package com.itheima.mapdemo1;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
​
/**
 * Map的练习
 */
public class MyMap5 {
    public static void main(String[] args) {
        HashMap<Student,String> hm = new HashMap<>();
​
        Student s1 = new Student("xiaohei",23);
        Student s2 = new Student("dapang",22);
        Student s3 = new Student("xiaomei",22);
​
        hm.put(s1,"江苏");
        hm.put(s2,"北京");
        hm.put(s3,"天津");
​
        //第一种:先获取到所有的键,再通过每一个键来找对应的值
        Set<Student> keys = hm.keySet();
        for (Student key : keys) {
            String value = hm.get(key);
            System.out.println(key + "----" + value);
        }
​
        System.out.println("===================================");
​
        //第二种:先获取到所有的键值对对象。再获取到里面的每一个键和每一个值
        Set<Map.Entry<Student, String>> entries = hm.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            Student key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "----" + value);
        }
        System.out.println("===================================");
        //第三种:
        hm.forEach(
                (Student key, String value)->{
                    System.out.println(key + "----" + value);
                }
        );
​
    }
}

4.forEach方法解析

bI77R3y.png!mobile

5.TreeMap集合

5.1TreeMap-原理解析【了解】

1.TreeMap-小结

  • TreeMap底层是红黑树结构

  • 依赖自然排序或者比较器排序,对键进行排序

  • 如果 键存储 的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则

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

  • 案例需求

    • 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历

    • 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序

  • 实现思路

    1.创建学生类

    2.创建TreeMap集合对象

    3.创建学生对象

    4.添加学生对象

    5.遍历输出

  • 代码实现

    学生类

    package com.itheima.maptest;
    ​
    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 String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                  '}';
        }
    ​
       /* @Override
        public int compareTo(Student o) {
            //按照年龄进行排序
            int result = o.getAge() - this.getAge();
            //次要条件,按照姓名排序。
            result = result == 0 ? o.getName().compareTo(this.getName()) : result;
            return result;
        }*/
    }

    测试类

    package com.itheima.maptest;
    
    import java.util.Comparator;
    import java.util.TreeMap;
    
    /**
     * 需求:创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String)。
     *           学生属性姓名和年龄,按照年龄进行排序并遍历。
     */
    public class Test1 {
        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("xiaohei",23);
            Student s2 = new Student("dapang",22);
            Student s3 = new Student("xiaomei",22);
    
            tm.put(s1,"江苏");
            tm.put(s2,"北京");
            tm.put(s3,"天津");
    
            tm.forEach(
                    (Student key, String value)->{
                        System.out.println(key + "---" + value);
                    }
            );
        }
    }

==扩展练习==

题目1

假如你有3个室友,请使用HashSet集合保存3个室友的信息;

信息如下:

赵丽颖,18

范冰冰,20

杨幂,19

要求:

1:室友以对象形式存在,包含姓名和年龄两个属性;

2:使用代码保证集合中同名同年龄的对象只有一份;(相同姓名和年龄的对象认为是同一个对象)

效果:

UzIry2f.png!mobile

参考答案:

测试类:
class Demo {
    public static void main(String[] args) {
        Student s1=new Student("赵丽颖",18);
        Student s2=new Student("范冰冰",18);
        Student s3=new Student("杨幂",19);
        HashSet<Student> hs=new HashSet<>() ;
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        System.out.println(hs);
    }
}
类文件:
package day9.No_1;
​
public class Student {
    private String name;
    private int age;
​
    public Student() {
    }
​
    public Student(String name, int age) {
        this.name = name;
        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 +
                '}';
    }
​
    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;
    }
}
​
​

题目2

请使用HashMap集合保存街道两旁的店铺名称;使用门牌号作为键,店铺名作为值,然后使用 三种方式 遍历输出;

信息如下:

101,阿三面馆

102,阿四粥馆

103,阿五米馆

104,阿六快递

要求:

1:键是整数,值是字符串;

2:输出的信息使用"--"链接

效果:

yyIfayF.png!mobile

参考答案:

package day9.No_2;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
​
public class Demo {
    public static void main(String[] args) {
        HashMap<Integer,String>hs=new HashMap<>() ;
        hs.put(101,"阿三面馆");
        hs.put(102,"阿四粥馆");
        hs.put(103,"阿五米馆");
        hs.put(104,"阿六快递");
        System.out.println("方式一遍历\t键值查找");
        System.out.println("=================");
        Set<Integer> keys = hs.keySet();
        for (Integer key : keys) {
            String value = hs.get(key);
            System.out.println(key+"--"+value);
        }
        System.out.println("方式二遍历\t键值对对象");
        System.out.println("=================");
        Set<Map.Entry<Integer, String>> entries = hs.entrySet();
        for (Map.Entry<Integer, String> entry : entries) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"--"+value);
        }
        System.out.println("方式三遍历\t使用接口");
        System.out.println("=================");
        hs.forEach(( i, s)->
            System.out.println(i+"--"+s)
        );//lambda简写格式
    }
}
​

题目3(综合题,有难度)

请使用TreeMap集合保存劳模信息,要求以劳模对象为键,家庭住址为值,并按照劳模的年龄从大到小排序后输出;

信息如下:

18岁的张三,北京

20岁的李四,上海

35岁的王五,天津

21岁的赵六,北京

19岁的田七,上海

要求:

1:劳模类中有姓名和年龄两个属性;

2:添加上述信息后,使用代码删除张三的信息

3:添加上述信息后,使用代码修改李四的家庭住址为郑州

4:使用至少两种方式遍历集合中的信息并输出;

效果:

JrqQbu7.png!mobile

参考答案:

此方式只能集合从大到小的规则才可以使用

package day9.No_3;
​
import java.util.*;
​
public class Demo {
    public static void main(String[] args) {
        Student s2 = new Student("李四", 24);
        Student s1 = new Student("张三", 23);
        Student s3 = new Student("王五", 25);
        Student s4 = new Student("赵六", 26);
        TreeMap<Student, String> ts = new TreeMap<>();
        ts.put(s1, "北京");
        ts.put(s2, "上海");
        ts.put(s3, "广东");
        ts.put(s4, "深圳");
        Set<Student> keySet = ts.keySet();
        try {
            for (Student key : keySet) {
                //使用代码删除张三的信息
                // 此时我们并没有使用迭代器删除方式,直接调用TreeMap集合方法进行了删除
                //但是只能删除从大到小排序规则的集合,不可以删除从小到大规则排序的集合
                if (key.getName().equals("张三")) {
                    ts.remove(key);
                    System.out.println("删除成功!");
                }
            }
        } catch (Exception e) {
            System.out.println("删除失败!违背了迭代器原理!可以试试集合倒着写");
        }
        for (Student key : keySet) {
​
            //使用代码修改李四的家庭住址为郑州
            if (key.getName().equals("李四")) {
                //增强for方法底层是迭代器遍历方式,不能修改set集合元素,
                // 而我们修改的是treeMap,所以并没有违背迭代器不能修改的原则
                ts.put(key, "郑州");
                System.out.println("修改成功");
            }
        }
​
        System.out.println(ts);
        System.out.println("遍历一:");
        for (Student key : keySet) {
            String value = ts.get(key);
            System.out.println(key.getAge() + "岁的" + key.getName() + "," + value);
        }
    }
​
​
​
    public static void Bianli(TreeMap<Student, String> ts) {
        System.out.println("遍历二:");
        ts.forEach((Student key,String value)->{
            System.out.println(key.getAge()+"岁的"+key.getName()+","+value);
​
        });
        System.out.println("遍历三:");
        Set<Map.Entry<Student, String>> entries = ts.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            Student key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key.getAge()+"岁的"+key.getName()+","+value);
        }
    }
}
​

迭代器进行删除修改:

package day9.No_3;
​
import java.util.*;
​
public class Demo1 {
    public static void main(String[] args) {
        Student s1 = new Student("张三", 23);
        Student s2 = new Student("李四", 24);
        Student s3 = new Student("王五", 25);
        Student s4 = new Student("赵六", 26);
        TreeMap<Student, String> ts = new TreeMap<>();
        ts.put(s1, "北京");
        ts.put(s2, "上海");
        ts.put(s3, "广东");
        ts.put(s4, "深圳");
        Set<Student> keySet = ts.keySet();
         Iterator<Student> iterator1 = keySet.iterator();
        while (iterator1.hasNext()) {
            Student key = iterator1.next();
            if (key.getName().equals("李四")) {
                iterator1.remove();
                System.out.println("删除成功");
            }
        }
        /*//bug代码:
        Iterator<Student> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            if (iterator.next().getName().equals("张三")) {
                ts.put(iterator.next(), "郑州");
            }//此逻辑不会编译报错,运行也不报错,但是逻辑不通,,但是会修改到下一个key的值,迭代器的默认指向下一个原理
        }*/
       /* for (Student key : keySet) {
            if (key.getName().equals("张三")){
                ts.put(key,"郑州");//该方法也可以对值进行修改
            }
        }*/
        Iterator<Student> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            Student key = iterator.next();
            if (key.getName().equals("张三")) {
                ts.put(key, "郑州");
                System.out.println("修改成功");
            }
        }
        System.out.println(ts);
        System.out.println("遍历一:");
        for (Student key : keySet) {
            String value = ts.get(key);
            System.out.println(key.getAge() + "岁的" + key.getName() + "," + value);
        }
        
    }
​
​
    public static void Bianli(TreeMap<Student, String> ts) {
        System.out.println("遍历二:");
        ts.forEach((Student key, String value) -> {
            System.out.println(key.getAge() + "岁的" + key.getName() + "," + value);
​
        });
        System.out.println("遍历三:");
        Set<Map.Entry<Student, String>> entries = ts.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            Student key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key.getAge() + "岁的" + key.getName() + "," + value);
        }
    }
}
​

类文件:

package day9.No_3;
​
import java.text.Collator;
import java.util.Locale;
​
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;
    }
​
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", 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 int compareTo(Student o) {
        int i = this.age - o.age;
        Collator instance = Collator.getInstance(Locale.CHINESE);
        i=i==0?instance.compare(this.name,o.name):i;
        return -i;//因为要从大到小,而默认规则是从小到大,排序根据返回的正负数排的,所以直接加负可以直接改变大小原则
    }
​
    @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;
    }
}
​

运行效果:

FZjuA3Z.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK