JavaSE学习笔记day15

news2024/11/15 19:32:29

零、 复习昨日

HashSet 不允许重复元素,无序

HashSet去重原理:

  • 先比较hashcode,如果hashcode不一致,直接存储
  • 如果hashcode值一样,再比较equals
  • 如果equals值为true,则认为完全一样,不存储即去重
  • 否则存储

如果使用的是空参构造创建出的TreeSet集合,那么它底层使用的就是自然排序,即放入TreeSet的元素都必须实现Comparable接口,重写方法compareTo

一、作业

  public static void main(String[] args) {
        String[] arr = {"a","b","c","a","b","c"};
        String[] strArr = setArray(arr);
        System.out.println(Arrays.toString(strArr ) );
    }

    // 第一题
    // 设计方法,将传入的数组去重后返回
    // 例如: 字符串数组:[“aa”,”bb”,”cc”,”aa”,”cc”,”bb”],将其去重变为[“aa”,”bb”,”cc”]
    public static String[] setArray(String[] arr) {

        // 遍历数组,取出一个,向set集合放一个,最后再变回数组
        HashSet<String> set = new HashSet<>( );
        for (String s : arr) {
            set.add(s);
        }
        String[] strArr = new String[set.size()];

        // 集合转数组
        String[] result = set.toArray(strArr);

        return result;
    }

注意: T[] toArray(T[] arr)

4 创建一个Teacher类 属性age name salary 
  创建10个Teacher对象 装入TreeSet中
  通过设置Teacher类 保证age大的在Treeset前面  
   age相同 
	salary小的在Treeset前面
    salary相同 name长度小的在Treeset前面
package com.qf.homework;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Teacher implements Comparable<Teacher>{

    private int age;
    private String name;
    private double salary;
    
    // 省略部分代码...

    @Override
    public int compareTo(Teacher o) {
        // 如果年龄相同,则继续判断
        if(o.getAge() - this.age == 0){
            // 再判断工资,如果工资相同,则继续判断
            if (this.salary - o.getSalary() == 0) {
                // 判断名字长度,如果名字长度一致,要保留该人名,所以不能返回0,随意返回一个1或者-1
                // 如果名字长度不一致,名字短的在前
                return this.name.length() - o.getName().length() == 0 ? 1 : this.name.length() - o.getName().length();
            } else {
                // 如果工资不同,工资低的在前
                return this.salary - o.getSalary() > 0 ? 1 : -1;
            }
        } else {
            // 如果年龄不同,年龄大在前
            return o.getAge() - this.age;
        }
    }
}
    public static void main(String[] args) {

        TreeSet<Teacher> treeSet = new TreeSet<>( );
        treeSet.add(new Teacher(18,"老邢",50000));
        treeSet.add(new Teacher(21,"老邢",50000));
        treeSet.add(new Teacher(19,"小老邢",40000));
        treeSet.add(new Teacher(19,"老邢",40000));
        for (Teacher teacher : treeSet) {
            System.out.println(teacher );
        }
    }

二、比较器排序

TreeSet是会对元素进行排序去重,有两种实现方案

  • 使用空参构造方法创建出的TreeSet,底层使用自然排序,即元素要实现Comparable接口才能实现排序
  • 第二种方案: 可以使用有参构造,在创建TreeSet集合时,传入一个Comparator 比较器,这样存入的元素就会按照该比较器指定的排序方案排序( 不再使用默认的自然排序)

TreeSet(Comparator comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。

使用步骤

  • 自定义类实现Comparator 接口
  • 重写compar(T o1,T o2)方法
    • o1 就是之前compareTo方法中的this,即正在存储的元素
    • o2 就是之前compareTo方法中的o,即以前存储过的元素
    • 方法返回值与之前compareTo方法的返回值一样
      • 返回0 去重
      • 返回负数放左边
      • 返回正数放右边
  • 在创建TreeSet时,创建该比较器对象,传入TreeSet的构造方法

练习: 把昨天的排序练习使用比较器排序再写一遍

学生语数外总成绩排序题目改写

// 学生成绩类
public class StudentScore{

    private String name;
    private int chinese;
    private int math;
    private int english;
    // set get...
    // 有参 无参构造
}
// 自定义成绩比较器
public class MyScoreComparator implements Comparator<StudentScore> {
    @Override
    public int compare(StudentScore o1, StudentScore o2) {
        return o2.getTotal() - o1.getTotal() == 0 ? 1 : o2.getTotal() - o1.getTotal();

    }
}
    public static void main(String[] args) {
        // 创建集合时指定成绩比较器
        TreeSet<StudentScore> set2 = new TreeSet<>(new MyScoreComparator() );
        set2.add(new StudentScore("zhang3",70,70,70 ));
        set2.add(new StudentScore("wang5",100,100,100 ));
        set2.add(new StudentScore("li4",80,80,80 ));
        set2.add(new StudentScore("zhao6",60,60,60 ));
        set2.add(new StudentScore("zhou7",90,90,90 ));

        for (StudentScore score : set2) {
            System.out.println(score );
        }
    }

三、Collections

类似于与Arrays,Collections是集合的工具类,方法都是静态的

  • Collections.reverse(List<?> list) 反转
  • Collections.shuffle(List<?> list) 混洗
  • Collections.sort(List<?> list) 排序
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(3);
        list.add(2);
        list.add(5);
        list.add(4);
        list.add(1);

        System.out.println(list );
        // 反转
        // Collections.reverse(list);
        //System.out.println(list );
        // 混洗
        //Collections.shuffle(list);
        // 排序,升序
        Collections.sort(list);
        System.out.println(list );

    }

四、Map<K,V>

Map代表双列集合,一次存储一对键值对(K,V)
Map是接口,代表是键映射到值的对象,一个Map不能包含重复的键,值允许重复.每个键最多只能映射到一个值,即可以通过键找到值,但是不能通过值找键.

方法都是非常常见的方法,但是Map是接口无法演示

Map有两个常用实现类

  • HashMap
  • TreeMap

五、HashMap

HashMap是Map的实现类,现在JDK8及以后底层是由数组+链表+红黑树实现
并允许使用 null 值和 null

HashMap存储的元素是不保证迭代顺序,存储的键不允许重复,值允许重复


除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同


补充: Hashtable是线程安全的map集合,效率低 ; HashMap是线程不安全的,效率高
ConcurrentHashMap 即安全又高效的Map集合

HashMap的容量和扩容: 初始容量16,加载因子0.75 阈值是 16 * 0.75,达到阈值扩容至原来的2倍
ps: 昨天学习的HashSet所有特性,其实就是HashMap的特性,包括去重原理

5.1 方法演示

构造方法

HashMap()
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity)
构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor)
构造一个带指定初始容量和加载因子的空 HashMap。
HashMap(Map<? extends K,? extends V> m)
构造一个映射关系与指定 Map 相同的新 HashMap。

方法

每个都很重要!!!

    public static void main(String[] args) {

        // 创建空的HashMap;
        HashMap<String,Integer> map = new HashMap<>();
        System.out.println(map );

        // 添加元素,一次添加一对,键值
        // put方法的返回值,如果该键之前没有映射值,返回null
        // 如果该键之前映射的有值,则将值覆盖,返回上次的旧值
        Integer v1 = map.put("a",1);
        System.out.println(v1 );

        Integer v2 = map.put("a", 2);
        System.out.println(v2 );

        Integer v3 = map.put("d", 4);
        System.out.println(v3 );
        map.put("b",2);
        System.out.println(map );

        // 取出元素
        // 通过键返回值
        Integer v = map.get("a");
        System.out.println(v );

        // 集合大小(元素个数)
        System.out.println(map.size() );

        // 集合是否为空
        System.out.println(map.isEmpty() );

        // 清空集合
        //map.clear();

        // 集合大小(元素个数)
        //System.out.println(map.size() );

        // 集合是否为空
        //System.out.println(map.isEmpty() );

        // 移除元素,根据键移除整个键值对,返回值
        Integer a = map.remove("a");
        System.out.println(a );

        System.out.println(map );
        
        
        /**
         *  boolean containsKey(Object key)
         *           判断集合中是否包含指定键,有则返回 true。
         *  boolean containsValue(Object value)
         *           判断集合中是否包含指定值,有则返回 true。
         */
        System.out.println(map.containsKey("A"));
        System.out.println(map.containsValue(11));
    }

5.2 迭代/遍历

Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容

  • Set keySet() 键集,返回一个Set集合,其中只有键
  • Collection values() 值集,返回一个Collection集合,其中只有值
  • Set<Map.Entry<K,V>> entrySet() 键值映射集,返回一个Set集合,其中放着key-value对象

5.2.1 键集

    public static void main(String[] args) {
        HashMap<String,Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);

        // 键集遍历
        Set<String> keySet = map.keySet();
        // 获得迭代器
        Iterator<String> iterator = keySet.iterator( );
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        System.out.println("-----------" );
        for(String key : keySet) {
            System.out.println(key );
        }
    }

5.2.2 值集

        // 值集
        Collection<Integer> values = map.values();
        Iterator<Integer> iterator1 = values.iterator( );
        while (iterator1.hasNext( )) {
            System.out.println(iterator1.next());
        }
        System.out.println("-----------" );
        for (Integer value : values) {
            System.out.println(value );
        }

5.2.3 键值映射集 [非常重要]

Entry是Map接口中的内部接口,代表是一个键值对,即包含键和值.
且该Entry接口中提供了关于操作单个键,值的方法

  • K getKey()
  • V getValue()
      // 获得键值映射集合Set,其中放着Entry
        Set<Entry<String,Integer>> entrySet = map.entrySet();
        Iterator<Entry<String,Integer>> iterator2 =  entrySet.iterator();
        while (iterator2.hasNext( )) {
            // 从迭代器取出的是Entry
            Map.Entry<String,Integer> entry = iterator2.next();
            // 通过entry可以单独获得键,值
            String key = entry.getKey( );
            Integer value = entry.getValue( );
            System.out.println(key +"-->" + value );
        }

        // for循环
        for(Map.Entry<String,Integer> entry : entrySet) {
            System.out.println(entry.getKey() +"--->" +entry.getValue() );
        }

image-20230224151747098

5.3 去重原理

HashMap的去重其实就是昨天讲的HashSet的去重,因为HashSet底层就是HashMap

  1. 在创建HashSet时,其实在底层创建了HashMap

    image-20230224152026062
  2. 在向set中添加元素时,其实是向map的key上添加

    image-20230224152119890

所以HashMap的键的去重原理就是

  • 向键存储数据时,先调用键的hashcode()方法
  • 如果hashcode值不一样则直接存储
  • 如果hashcode值一样,再调用元素的equals()方法
  • 如果equals方法返回false,则存储
  • 如果equals方法返回true,则不存储

5.4 HashMap的应用

场景一: 适合有关联映射的场景

设计方法,传入字符串,输出该字符串中每个字符出现的次数,使用HashMap实现
例如: “abcHelloabcWorld”,输出 a出现2次,b出现2次,l出现3次,H出现1次

   /**
     * 倒推: a --> 3  b --> 2
     * @param str
     */
    public static void cishu(String str) {
        String[] strArr = str.split("");
        System.out.println(Arrays.toString( strArr) );

        HashMap<String, Integer> map = new HashMap<>( );

        for (int i = 0; i < strArr.length; i++) {
            String s = strArr[i];
            if (!map.containsKey(s)) {
                map.put(s,1);
            } else {
                Integer count = map.get(s);
                count++;
                map.put(s,count);
            }
        }

        // System.out.println(map );
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet( );
        for (Map.Entry<String,Integer> entry :entrySet) {
            String s = entry.getKey( );
            Integer count = entry.getValue( );
            System.out.println("字符"+s+",出现"+count+"次" );

        }
    }

场景二: Map可以当实体类对象

public class Student{
    private int age;
    private String name;
    // ...
    
}
Student s1 = new Student(18,"zs");
s1.getAge();
s1.getName();

使用Map模拟对象

HashMap<String, Object> stu = new HashMap<>( );
stu.put("age",18);
stu.put("name","zs");
stu.put("sex","男");

LinkedHashMap: …

六、TreeMap

TreeMap底层是红黑树(平衡二叉树的一种)
同样式存储键值对,键不允许重复且还会排序
默认是根据键元素的自然顺序排序或者,根据创建TreeMap时指定的Comparator比较器来排序

6.1 方法演示

方法详见api

   public static void main(String[] args) {

        TreeMap<String, Integer> map = new TreeMap<>( );
        map.put("b",2);
        map.put("e",5);
        map.put("a",1);
        map.put("a",2);
        map.put("d",4);
        map.put("c",3);

        // 其他正常的map方法...
        // 三个遍历方法...

        // 特殊的,有关于头尾操作的方法
        // 获得排序后的第一个
        String key = map.firstKey( );

        // 获得排序后的第一个Entry
        Map.Entry<String, Integer> entry = map.firstEntry( );
        System.out.println(entry );
    }

6.2 TreeMap排序去重原理

昨天学习的TreeSet的底层其实就是TreeMap

  • 创建TreeSet时,创建TreeMap

    image-20230224163057509
  • 向set集合添加元素时,其实是向TreeMap的键添加元素

    image-20230224163141732

即TreeMap的排序去重原理是什么?其实如果自然排序就是compareTo(),如果是比较器排序就是compar()方法

  • 方法返回0 去重
  • 方法返回负数 放在树左侧
  • 方法返回正数 放在树的右侧

七、总结

集合体系中最重要最常见的两个集合是ArrayList,HashMap

其他的,

  • 记住常用的API(crud和遍历)
  • 记住List和Set区别
  • 记住ArrayList和LinkedList区别
  • 记住HashMap扩容,去重原理
  • 记住TreeMap的排序去重原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/372331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

_improve-1

类型及检测方式 1. JS内置类型 JavaScript 的数据类型有下图所示 其中&#xff0c;前 7 种类型为基础类型&#xff0c;最后 1 种&#xff08;Object&#xff09;为引用类型&#xff0c;也是你需要重点关注的&#xff0c;因为它在日常工作中是使用得最频繁&#xff0c;也是需要…

C/C++每日一练(20230226)

目录 17. 电话号码的字母组合 37. 解数独 51. N 皇后 52. N皇后 II 89. 格雷编码 90. 子集 II 17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电…

java spring AOP 完全注解开发

我们先创建一个项目 然后引入java spring aop的依赖 然后 在src下创建目录 我这里 直接就叫 Aop了 下面创建一个User类 参考代码如下 package Aop;import org.springframework.stereotype.Component;Component public class User {public void add(){System.out.println(&qu…

Allegro如何锁定报表界面操作指导

Allegro如何锁定报表界面操作指导 用Allegro做PCB设计的时候,进行测量的时候,比如测量器件两个PIN中间的间距,如下图,会有一个报表显示 但是当运行下一个命令的时候,报表会被自动关闭掉。 但是有时我们需要报表界面仍被保留 下面介绍如何将报表界面进行锁定,不受下一个…

新氧2023年财务业绩预测:退市风险大幅降低,收入增长将放缓

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 公司进展 与新氧&#xff08;SY&#xff09;有关的两个重要积极进展值得一提。 第一个积极进展是新氧的退市风险已在很大程度上降低。 2023年1月6日&#xff0c;新氧披露&#xff0c;它已经“重新符合纳斯达克规定的股价每…

AIR32F103(九) CAN总线的通信和ID过滤机制及实例

目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告AIR32F103(二) Linux环境和LibOpenCM3项目模板AIR32F103(三) Linux环境基于标准外设库的项目模板AIR32F103(四) 27倍频216MHz,CoreMark跑分测试AIR32F103(五) FreeRTOSv202112核心库的集成和示例代码AIR32F103(六) ADC,I2S…

Zookeeper完全分布式集群服务

准备好3台服务器:[x]A-> centos7s:192.168.19.1[x]B-> centos7_1:192.168.19.2[x]C-> centos7_2:192.168.19.3配置Zookeeper安装目录在3台宿主机配置zookeeper安装目录&#xff1a;/docker/develop/zookeeper并且在文件夹创建 data 和logs 目录&#xff1a;mkdir -p /…

STM32Cube串口USART发送接收数据

本文代码使用 HAL 库。 文章目录前言一、USART 同步/异步串行接收/发送器二、USART 原理图三、CubeMX 创建工程四、usart.c 文件解析五&#xff0c;设计实验&#xff1a;在 串口输入字符点亮led实验现象&#xff1a;总结前言 这篇文章介绍 实现 USART 异步模式下 通过 串口助手…

去了字节跳动,才知道年薪40W的测试居然有这么多?

今年大环境不好&#xff0c;内卷的厉害&#xff0c;薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了&#xff1a; 哪家互联网公司薪资最‘厉害’&#xff1f; 下面的评论多为字节跳动&#xff0c;还炸出了很多年薪40W的测试工程师 我只想问一句&#xff0c;现在的…

【设计模式】 观察者模式介绍及C代码实现

【设计模式】 观察者模式介绍及C代码实现 背景 在软件构建过程中&#xff0c;我们需要为某些对象建立一种“通知依赖关系”&#xff0c;即一个对象&#xff08;目标对象&#xff09;的状态发生改变&#xff0c;所有的依赖对象&#xff08;观察者对象&#xff09;都将得到通知。…

连续隐身四天、被传退出德云社,于谦未参加相声大会的原因找到了

欲戴皇冠&#xff0c;必受其重。意思就是一个人拥有一定的地位和声望&#xff0c;就会承担由此带来的责任和压力。 就拿德云社郭德纲搭档于谦来说&#xff0c;虽然他是一个谦虚低调的人&#xff0c;但是因为郭德纲老师名气太大&#xff0c;也让于谦伴随着一起名声鹊起。于谦老师…

chatgpt的原理 第三部分

对话 我们是如何学会中文的&#xff1f;从0岁开始&#xff0c;听、说&#xff0c;也就是对话。 我们是如何学外语的&#xff1f;看教材&#xff0c;听广播&#xff0c;背单词。唯独缺少了对话&#xff01;正是因为缺少了对话这个高效的语言学习方式&#xff0c;所以我们的英语…

8个小程序开源项目助你快速搭建小程序

今天和大家分享几个小程序开源项目, 帮助我们轻松搭建自己的小程序应用. 我会从大家最熟悉的小程序UI组件, 到可视化库, 再到完整项目, 一一和大家介绍.小程序UI组件库小程序多端开发框架小程序可视化图表库经典小程序开源项目小程序UI组件库1. vant-weappVant Weapp 是移动端 …

MXNet中使用卷积神经网络textCNN对文本进行情感分类

在图像识别领域&#xff0c;卷积神经网络是非常常见和有用的&#xff0c;我们试图将它应用到文本的情感分类上&#xff0c;如何处理呢&#xff1f;其实思路也是一样的&#xff0c;图片是二维的&#xff0c;文本是一维的&#xff0c;同样的&#xff0c;我们使用一维的卷积核去处…

LLVM程序分析与编译转换框架论文分享

LLVM 2004年论文原文 概述 本文描述了 LLVM&#xff08;低级虚拟机&#xff09;&#xff0c;一种编译器框架&#xff0c;旨在通过在编译时、链接时、运行时&#xff0c;以及运行之间的空闲时间。 LLVM 以静态单一赋值 (SSA) 形式定义了一种通用的低级代码表示&#xff0c;具有…

多区域的OSPF实战配置

多区域的OSPF实战配置 需求 如图配置设备的接口IP地址如图规划OSPF网络的区域要求每个设备的 router-id 都是 x.x.x.x&#xff08;x是每个路由器的名字&#xff09;确保不同的PC之间可以互通 拓扑图 配置命令 PC1&#xff1a; 192.168.1.1 255.255.255.0 192.168.1.254PC2:…

【手把手一起学习】(六) Altium Designer 20 STM32核心板Demo----PCB设计

1 PCB设计 PCB设计是制作STM32核心板的关键步骤&#xff0c;其关系到最终生产厂家制作的电路板能否正常使用&#xff0c;PCB设计包括布局&#xff0c;裁板&#xff0c;布线&#xff0c;覆铜&#xff0c;DRC检查等&#xff0c;其中要求、细节、技巧比较多&#xff0c;以后会更详…

redis(7)哈希Hash

哈希Hash Redis hash 是一个键值对集合。 Redis hash 是一个 string 类型的 field 和 value 的映射表&#xff0c;hash 特别适合用于存储对象。 类似 Java 里面的 Map<String,Object>。 用户 ID 为查找的 key&#xff0c;存储的 value 用户对象包含姓名&#xff0c;年…

西北工业大学大学物理(II)选填解析2019-2020期末

2 又是考查“一个电子和一个光子具有相同的波长&#xff0c;则二者动量相等。”4 斯特恩盖拉赫实验&#xff0c;原子的自旋磁矩取向量子化。7 通常我们感受不到电子的波动性。因为其波长短&#xff0c;其实也就是粒子运动速率高。10 考查无限长直导线周围B分布。常见的模型要记…

【035】基于Vue的电商推荐管理系统(含源码数据库、超详细论文)

摘 要&#xff1a;基于Vue&#xff0b;Nodejs&#xff0b;mysql的电商推荐管理系统&#xff0c;这个项目论文超详细&#xff0c;er图、接口文档、功能展示、技术栈等说明特别全&#xff01;&#xff01;&#xff01; &#xff08;文末附源码数据库、课设论文获取方式&#xff0…