JAVA教程 从入门到精通 Day18

11.10 Set

**Set :**无序,不可重复,去重

  • **无序:**存放的顺序与内部真实存储的顺序不一致
  • **去重:**集合不包含元素对e1和e2 ,使得e1.equals(e2)和最多一个null元素
  • **新增功能:**static Set of(E… elements) 返回包含任意数量元素的不可修改集
  • 遍历方式:
    • foreach
    • iterator迭代器

11.11 TreeSet

TreeSet :

  • 底层结构 : 红黑树
  • **特点 :**查询效率较高,自动把数据做升序排序
  • 底层是由TreeMap维护的
  • **新增功能:**新增了一些与比较大小相关的方法
  • 遍历方式 :
    • foreach
    • iterator迭代器
  • 注意 :

TreeSet需要存储相同类型的数据,因为会默认存在比较排序

11.12 内部比较器

TreeSet存储javabean类型的数据

**去重与排序:**都是根据比较规则实现的,与equals没有关系

比较规则:

  • 内部比较器|内部比较规则|自然排序 : 比较规则定义在javabean类型的内部
  • javabean类型实现Comparable接口,重写compareTo(T o)方法,在方法中定义比较规则
package Tuesday;

import java.util.TreeSet;

public class TreeSet2 {
    public static void main(String[] args) {
        TreeSet<Teacher> sc=new TreeSet<>();
        sc.add(new Teacher(01,"wang",10000));
        sc.add(new Teacher(04,"chang",23000));
        sc.add(new Teacher(03,"zhao",16000));

        System.out.println(sc);
    }
}

package Tuesday;

public class Teacher implements Comparable<Teacher> {
    private int id;
    private String name;
    private int sal;

    public Teacher() {
    }

    public Teacher(int id, String name, int sal) {
        this.id = id;
        this.name = name;
        this.sal = sal;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSal() {
        return sal;
    }

    public void setSal(int sal) {
        this.sal = sal;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sal=" + sal +
                '}';
    }

    @Override
    public int compareTo(Teacher o) {
        return this.sal-o.sal;
        //return this.name.compareTo(o.name);
    }
}

11.13 外部比较器

外部比较器|外部比较规则|定制排序 : 比较规则定义在javabean类型的外部

定义一个实现类,实现Comparator接口,重写int compare(T o1, T o2),在方法中定义比较规则

package Tuesday;

import java.util.Comparator;
import java.util.TreeSet;

public class Test1 {
    public static void main(String[] args) {

//        匿名内部类:简化没有类自身作用的实现类
        Comparator<Emp> se=new Comparator<Emp>() {  //实现类的类体
            @Override
            public int compare(Emp o1, Emp o2) {
                return Double.compare(o1.getSal(),o2.getSal());
            }
        };

//        lambda表达式:简化匿名内部类对象 要求必须为函数式接口才能简化
//        lambda表达式作为实参传递 -> 可以把行为作为参数传递
        se=(o1,o2)->o1.getId()- o2.getId();

        TreeSet<Emp> ss=new TreeSet<>(se);
        TreeSet<Emp> sd=new TreeSet<>(new Sc());
        ss.add(new Emp(04,"wang",18000));
        ss.add(new Emp(03,"chang",16500));
        ss.add(new Emp(02,"zhao",19000));

        System.out.println(ss);
    }
}

//外部比较器
    /*
        调用compare方法做两个数据的比较
            compare(t1,t2)
            返回值:
                =0       t1==t2
                <0       t1<t2
                >0       t1>t2
     */
class Sc implements Comparator<Emp>{

    @Override
    public int compare(Emp o1, Emp o2) {
        return Double.compare(o1.getSal(),o2.getSal());
    }
}

package Tuesday;

public class Emp {
    private int id;
    private String name;
    private double sal;

    public Emp() {
    }

    public Emp(int id, String name, double sal) {
        this.id = id;
        this.name = name;
        this.sal = sal;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sal=" + sal +
                '}';
    }
}

11.14 HashSet

HashSet:

  • **底层结构:**哈希表(数组+链表+红黑树)
  • **特点:**查询,增删效率高 ,去重,无序

底层是由HashMap维护的

  • 遍历:
    • foreach
    • iterator迭代器
  • **新增方法 :**无
  • 注意:
    • 此类允许null元素
    • 此实现不同步

练习:定义HashSet存储javabean类型得到数据,实现去重,测试使用

去重 :数据的类型要求重写hashCode与equals方法

package Tuesday;

import java.util.HashSet;

public class HashSet1 {
    public static void main(String[] args) {
        HashSet<Test2> sc=new HashSet<>();
        sc.add(new Test2("wangchao",22,"男"));
        sc.add(new Test2("changkun",29,"男"));
        sc.add(new Test2("zhaoshixiang",24,"男"));
        sc.add(new Test2("wangchao",22,"男"));

        System.out.println(sc);
    }
}


package Tuesday;

import java.util.Comparator;
import java.util.Objects;

public class Test2 {
    private String name;
    private int age;
    private String gender;

    public Test2() {
    }

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

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Test2 test2 = (Test2) o;
        return age == test2.age && Objects.equals(name, test2.name) && Objects.equals(gender, test2.gender);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, gender);
    }

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

11.15 Map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l7dHWyHE-1647963230298)(D:\Notes\笔记.assets\QQ截图20220322153153.png)]

**Map :**无序的,去重的 【键值对数据的集合

键值对->映射关系

价值对:K-V

K键 :无序的,去重的|唯一的 —> Set

V值 :无序的,可重复 —> Collection

  • 注意:

K-V 可以为任意引用数据类型

  • 特点:
    • 一个key只能对应一个Value
    • key相同value覆盖

遍历方式:
1.values 获取所有键值对的值

​ Collection values() 返回此映射中包含的值的Collection视图

​ 2.keySet 获取所有键值对的key,根据key获取value

​ Set keySet() 返回此映射中包含的键的Set视图

​ 3.entrySet 获取所有的键值对,每一个键值对都是一个Entry类型 —> 表示一个键值对

​ Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射的Set视图。

package Tuesday;

import java.util.*;

public class Map1 {
    public static void main(String[] args) {
        Map<Integer,String> sc=new HashMap<>();
        sc.put(1,"浩克");
        sc.put(2,"钢铁侠");
        sc.put(3,"美国队长");
        sc.put(4,"黑寡妇");
        sc.put(5,"蜘蛛侠");

        System.out.println(sc.get(4));
        System.out.println(sc.containsKey(9));
        System.out.println(sc.containsValue("蜘蛛侠"));
        System.out.println(sc.remove(2));
        System.out.println(sc.replace(1, "浩克", "钢铁侠"));
        System.out.println(sc.size());
        System.out.println("==================");
        System.out.println(sc);

        Map<Integer,String> ss=Map.of(12,"惊奇队长",23,"灭霸");
        System.out.println(ss);

        System.out.println("=========值===========");
        Collection<String> sf=sc.values();
        for (String se:sf){
            System.out.println(se);
        }

        System.out.println("=======键=======");
        Set<Integer> sx=sc.keySet();
        Iterator<Integer> sz=sx.iterator();
        while(sz.hasNext()){
            Integer key=sz.next();
            System.out.println(key+"--->"+sc.get(key));
        }

        System.out.println("===========entrySet=============");
        Set<Map.Entry<Integer,String>>  dui=sc.entrySet();
        for (Map.Entry<Integer,String> sv:dui){
            System.out.println(sv.getKey()+"--->"+sv.getValue());
        }
    }
}

11.16 TreeMap

TreeMap :

  • **底层:**红黑树

存储键值对类型的数据,自动升序排序,去重的

  • 去重,排序:

根据键值对的key实现,与value本身无关

  • 注意:

  • TreeSet底层是由TreeMap

  • 此实现不同步

  • **测试:**使用TreeMap存储键值对数据,key要求为javabean类型教师数据,value存储教授学科,测试存储练

    习是否可以根据key实现去重,测试是否为升序排序,要求根据教师编号做升序排序

    去重|排序:根据key的类型的比较规则,key的数据类型实现内部比较器,传递外部比较规则

package Tuesday;

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

public class TreeMap1 {
    public static void main(String[] args) {
//        匿名内部类
        Comparator<Teacher1> sf=new Comparator<Teacher1>() {
            @Override
            public int compare(Teacher1 o1, Teacher1 o2) {
                return o1.getNum()-o2.getNum();
            }
        };
//        Lambad
        sf=(o1,o2)->o1.getNum()-o2.getNum();
        TreeMap<Teacher1,String> sc=new TreeMap<>(sf );
        sc.put(new Teacher1(1,"zhang",23),"语文");
        sc.put(new Teacher1(2,"wang",44),"历史");
        sc.put(new Teacher1(3,"chang",26),"英语");

        System.out.println(sc);
    }
}
class Yest implements Comparator<Teacher1> {

    @Override
    public int compare(Teacher1 o1, Teacher1 o2) {
        return o1.getNum()-o2.getNum();
    }
}

package Tuesday;

public class Teacher1 implements Comparable<Teacher1> {
    private int num;
    private String name;
    private int age;

    public Teacher1() {
    }

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

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    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 "Teacher1{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Teacher1 o) {
        return this.num-o.num;
    }
}

11.17 HashMap

HashMap :

基于哈希表的Map接口的实现。 此实现提供了所有可选的映射操作,并允许null值和null键

HashSet 底层是由HashMap

  • **底层结构:**哈希表(数组+链表+红黑树)

  • 哈希表:

    • **数组 :**节点数组Node[ ] --> 要求数组的长度为2的整数次幂

    • **Node :**int hash,Object key,Object value,Node next

      每个索引位置存储的为一个单向链表的首节点(尾插法)

      当链表的长度>8,数组的长度>64,会把链表优化成为红黑树

      当链表的长度>8,但是数组的长度不大于64,这时候会实现扩容(数组的扩容)

    • **初始容量:**哈希表中的数组默认的初始长度 16

      ​ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

      ​ 数组的容量最大容量 : static final int MAXIMUM_CAPACITY = 1 << 30;

    • **加载因子:**0.75 一般不建议改变

      • 默认加载因子 : static final float DEFAULT_LOAD_FACTOR = 0.75f ;
    • **扩容阀值 threshold:**扩容的临界值 数据的个数size>数组的长度*加载因子 就会扩容

    • **扩容机制:**原容量的2倍 int newCap = oldCap << 1

    • **新增功能:**无

HashMap的哈希表存储数据的过程:

1.根据key计算哈希值

通过key的hashCode方法的返回值进一步进行hash算法的运算,得到的整数

int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

2.调用putVal方法实现添加数据(hash,key,value)

  1. 判断是否是第一次调用put方法做添加 if ((tab = table) == null || (n = tab.length) == 0)

​ 如果是第一次添加,直接调用resize()实现扩容

  1. 计算位桶的索引 int index = (n - 1) & hash

  2. 判断哈希表结构的数组table[index]是否存在数据

​ ① 如果不存在数据,证明没有头节点,创建新节点,放入当前数组的对应索引位置作为头节点

​ table[index] = new Node<>(hash, key, value, next);

​ ② size数据的个数+1,判断是否>扩容的阀值,如果大于需要调用resize方法进行扩容,如果不大于,不需要扩容直接返回null

​ if (++size > threshold) resize();

​ return null;

​ ③ 如果存在数据,作为链表的头结点,遍历这个链表,拿到每一个节点的key与hash值判断是否与要添加的key

和hash相同,如果相同,value覆盖

​ if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))

​ value覆盖之后,返回被覆盖的value

​ V oldValue = e.value;

​ e.value = value;

​ return oldValue;

去重 : 根据key做去重,要求key的数据类型重写hashCode与equals方法

11.19 HashMap与Hashtable

Hashtable 与 HashMap之间的区别:

**共同点 :**都是Map接口的实现类,底层结构都是哈希表

异同点 :

1.继承体系不同

2.线程是否安全不同
HashMap 线程不安全|不同步

​ Hashtable 线程安全的|同步的

3.扩容机制不同

​ HashMap扩容机制 :每次扩容原容量的2倍

​ int newCap = oldCap << 1

​ Hashtable扩容机制 :原容量的2倍+1

​ int newCapacity = (oldCapacity << 1) + 1;

4.键值对数据null值的要求不同

​ HashMap 可以存储null值的key与value

​ Hashtable key与value都不为null

5.计算hash值与位桶索引index的算法不同

​ HashMap :

​ int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

​ int index = (n - 1) & hash

Hashtable :

​ int hash = key.hashCode();

​ int index = (hash & 0x7FFFFFFF) % tab.length;

如何处理HashMap线程不安全问题:

​ 1.使用Hashtable

​ 2.使用Collections工具类中static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持

的同步(线程安全)映射

​ 3.juc高级并发编程包 ConcurrentHashMap<K,V> —> 线程安全的哈希表

11.20 Collections工具类

Collections :

​ 操作集合的工具类

​ 静态工厂

void sort(List)

//对List容器内的元素排序,排序的规则是按照升序进行排序

void shuffle(List)

//对List容器内的元素进行随机排列

void reverse(List)

//对List容器内的元素进行逆续排列

void fill(List, Object)

//用一个特定的对象重写整个List容器

int binarySearch(List, Object)

//对于顺序的List容器,采用折半查找的方法查找特定对象

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值