02-Java集合之双列集合,如HashMap,Hashtable,Properties,TreeMap的底层结构

news2024/9/23 13:26:52

双列集合

添加/获取/删除键值对原理

哈希表/散列表是一种将数组和单向链表融合在一起的数据结构

  • 数组在查询方面效率很高,单向链表在随机增删方面效率较高,哈希表将以上的两种数据结构融合在一起后充分发挥它们各自的优点

双列集合以key和value这种键值对方式存储数据: key和value都是存储对象的内存地址,其中key起到主导的地位,value是key的附属

  • 集合存储键值对的key无序不可重复: 如果key重复了value会覆盖
  • 集合存储键值对的key需要同时重写hashCode()+equals()方法: 先调用key的hashCode()方法确定单向链表下标,后调用key的equals()方法判断是否重复
  • 集合存储键值对的vlaue需要同时重写equals()方法: 调用value的equals()方法判断是否包含某个value

双列集合添加/获取/删除元素的流程: 都是先得到对象的Hash值并转换成对应单向链表下标,然后与该单向链表上的元素进行比较

  • 先调用key的hashCode方法得到一个哈希值,这个哈希值会经过哈希算法转换成对应单向链表的下标,如果该单向链表上没有元素直接存储即可
  • 只有对应的单向链表上有元素时,才会调用key的equals方法与该链表中的元素进行比较
    • 添加: key重复则覆盖对应键值对的value
    • 获取: key相等则返回对应键值对的value值
    • 删除: key相等则删除对应的键值对
  • 哈希碰撞: 对象返回的hash值相同转换的单向链表一定相同,但对象返回的hash值不同经过哈希算法转换的单向链表下标也可能相同

如果对象的hashCode和equals方法的返回值设置不好就会造成散列分布不均匀现象,一般使用IDEA一起生成equals+hashCode方法

  • hashCode方法返回固定值: 导致底层哈希表变成了纯单向链表
  • hashCode方法返回不同值: 导致底层哈希表就成为了一维数组
  • 如果equals方法返回true那么hashCode方法返回值必须一样: 相同对象必须在同一个单向链表上比较,只有这样才能保证其他链表上没有该对象

在这里插入图片描述

重写hashCode方法

静态的内部类HashMap.Node

public class HashMap{
    // HashMap底层实际上就是一个数组(一维数组)
    Node<K,V>[] table;
    static class Node<K,V> {
        // 哈希值是调用key的hashCode()方法的执行结果,hash值会通过哈希算法转换存储成数组的下标
        final int hash; 
        // 存储到Map集合中的那个key
        final K key; 
        // 存储到Map集合中的那个value
        V value; 
        // 下一个节点的内存地址
        Node<K,V> next; 
    }
}

使用IDEA一起生成equals+hashCode方法以达到散列分布均匀的效果即每个单向链表上分布的节点个数是平均的

public class HashSetTest {
    public static void main(String[] args) {
		// 创建对象
        Student s1 = new Student("zhangsan");
        Student s2 = new Student("zhangsan");

        // 重写equals方法之后是true
        System.out.println(s1.equals(s2)); 
		// 同一个对象的hash值相同,不同对象的hash值一般不相同
        System.out.println("s1的hashCode=" + s1.hashCode()); //284720968(没重写),-1432604525(重写hashCode之后)
        System.out.println("s2的hashCode=" + s2.hashCode()); //122883338(没重写),-1432604525(重写hashCode之后)

        //s1.equals(s2)结果是true表示s1和s2是一样的,那么往HashSet集合中放的话按说只能放进去1个
        Set<Student> students = new HashSet<>();
        students.add(s1);
        students.add(s2);
        // 结果是2并不符合HashSet集合元素无序不可重复的特点
        System.out.println(students.size()); 
    }
}

// 如果equals方法返回是true,hashCode方法返回值必须相同的原则,这样才能保证在同一个单向链表中对相同元素进行比较
class Student {
    private String name;
    public Student(String name) {
        this.name = name;
    }
    //构造 + set 和 get 方法....

    // 如果学生名字一样,表示同一个学生
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        // 以下这个方法可以保证如果两个对象经过equals比较相同时,那么它们hashCode方法返回值一定相同的原则
        return Objects.equals(name, student.name);
    }

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

双列集合继承结构图

在这里插入图片描述

超级父接口Map

常用方法

集合中元素的增删改查方法,集合中存储键值对的Key需要同时重写hashCode()+equals()方法

方法名功能
V put(K key, V value)向Map集合中添加键值对
V get(Object key)通过key获取value,key不存在返回nul
getOrDefault(key ,默认值)通过key获取value, 如果key不存在则返回指定的默认值
V remove(Object key)通过key删除键值对
void clear()清空Map集合
Collection< V > values()获取Map集合中所有的value,返回一个Collection类型的集合
Set< K > keySet()获取Map集合所有的key,返回一个存储所有key的Set类型的集合
Set<Map.Entry<K,V>>entrySet()将Map集合转换成Set集合

集合中元素的判断方法

方法名功能
boolean containsKey(Object key)判断Map中是否包含某个key,先确定单向链表,再调用equals方法与链表上的元素进行比较
boolean containsValue(Object value)判断Map中是否包含某个value,底层调用的value的equals方法与集合中键值对的value挨个进行比较
boolean isEmpty()判断Map集合中是否为空
int size()获取Map集合中键值对的个数
public class MapTest01 {
    public static void main(String[] args) {
        // 创建Map集合对象
        Map<Integer, String> map = new HashMap<>();
       
        // 测试put方法,向Map集合中添加键值对
        map.put(1, "zhangsan"); // 1在这里进行了自动装箱
        map.put(2, "lisi");
        map.put(3, "wangwu");
        map.put(4, "zhaoliu");
        
        // 测试get方法,通过key获取value
        String value = map.get(2);
        System.out.println(value);
        
        // 测试方法,通过key获取value,如果key不存在则返回指定的默认值
        String value1 = map.getOrDefault()(5,"zhaoliu");// map中不存在5,则返回默认值
        System.out.println(value1);
        
        
        // 测试size方法,获取键值对的数量
        System.out.println("键值对的数量:" + map.size());
        
        // 测试remove方法,通过key删除键值对
        map.remove(2);
        System.out.println("键值对的数量:" + map.size());
        
        // 测试containsKey方法,判断是否包含某个key
        System.out.println(map.containsKey(new Integer(4))); // true
        // 判断containsValue方法,判断是否包含某个value
        System.out.println(map.containsValue(new String("wangwu"))); // true

        // 测试values方法,获取所有的value
        Collection<String> values = map.values();
        // foreach
        for(String s : values){
            System.out.println(s);
        }

        // 测试clear方法,清空map集合
        map.clear();
        System.out.println("键值对的数量:" + map.size());
        
        // 测试isEmpty()方法,判断集合是否为空
        System.out.println(map.isEmpty()); // true
    }
}

深入entrySet()方法

entrySet()方法: Map集合转换成的Set集合中的元素的类型是Map.Entry<K,V>类型

  # Map集合存储对象
  key             value
  ----------------------------
  1               zhangsan
  2               lisi
  3               wangwu
  4               zhaoliu

  #Set集合存储对象,集合中元素的类型是Map.Entry类型
  1=zhangsan
  2=lisi     
  3=wangwu
  4=zhaoliu

Map.Entry和String一样都是一种类型的名字,只不过Map.Entry是Map中静态内部类,并且这个类声明的时候指定了泛型

public class MyMap {
    // 声明一个静态内部类并且指定了泛型, 类名叫做:MyMap.MyEntry<K,V>
    public static class MyEntry<K,V> {
        // 内部类中的静态方法
        public static void m1(){
            System.out.println("静态内部类的m1方法执行");
        }

        // 内部类中的实例方法
        public void m2(){
            System.out.println("静态内部类中的实例方法执行!");
        }

    }
    
    public static void main(String[] args) {
        // 执行内部类中的静态方法
     	MyMap.MyEntry.m1();

        // 创建静态内部类对象,执行内部类中的实例方法
      	MyMap.MyEntry mm =  new MyMap.MyEntry()
        mm.m2();
        
        // 声明一个Set集合,存储的对象类型是String类型
        Set<String> set2 = new HashSet<>();

        // 声明一个Set集合,存储的对象是MyMap.MyEntry类型,没有指定泛型默认是Object类型
        Set<MyMap.MyEntry> set = new HashSet<>();

		// 声明一个Set集合,存储的对象是MyMap.MyEntry<Integer, String>类型
        Set<MyMap.MyEntry<Integer, String>> set3 = new HashSet<>();
    }
}

Map集合的遍历

第一种: 调用Map集合的keySet()方法获取存储集合所有key的Set集合,使用迭代器或者foreach的方式遍历Set集合中的每一个key并通过key获取value

// 向Map集合中添加元素
Map<Integer, String> map = new HashMap<>();
map.put(1, "zhangsan");
map.put(2, "lisi");

// 获取所有的key,所有的key存储在一个Set集合
Set<Integer> keys = map.keySet();

// 使用迭代器的方式遍历keys集合,通过key获取value
Iterator<Integer> it = keys.iterator();
while(it.hasNext()){
    // 取出其中一个key
    Integer key = it.next();
    // 通过key获取value
    String value = map.get(key);
    System.out.println(key + "=" + value);
}
// 使用foreach的方式遍历key,通过key获取value
for(Integer key : keys){
    System.out.println(key + "=" + map.get(key));
}

第二种(推荐): 调用Map集合的entrySet()方法直接把Map集合转换成Set集合,遍历Set集合中的每一个节点对象,通过节点对象的方法获取key和value

在这里插入图片描述

// 向Map集合中添加元素
Map<Integer, String> map = new HashMap<>();
map.put(1, "zhangsan");
map.put(2, "lisi");

// 把Map集合转换成Set集合,Set集合中元素的类型是Map.Entry
Set<Map.Entry<Integer,String>> set = map.entrySet();

// 使用迭代器的方式遍历Set集合,集合中存储的Node对象有Key和Value属性
Iterator<Map.Entry<Integer,String>> it2 = set.iterator();
while(it2.hasNext()){
    Map.Entry<Integer,String> node = it2.next();
    Integer key = node.getKey();
    String value = node.getValue();
    System.out.println(key + "=" + value);
}

// 使用foreach的方式遍历Set集合
for(Map.Entry<Integer,String> node : set){
    System.out.println(node.getKey() + "--->" + node.getValue());
}

Map接口实现类

HashMap集合(哈希表)

HashMap底层实际上就是个一维数组,这个数组中每一个元素是一个单向链表,集合中存储键值对的key无序不可重复

  • 无序: 添加的键值对不一定挂到哪个单向链表上
  • 不可重复: 先调用key的hashCode方法确定单向链表下标,后调用key的equals方法判断是否相等, 如果key重复了value会覆盖
  • key和value允许为null: 调用key的hashCode方法或者value的equals方法时如果为null会做判断,集合的key允许为null但只能有一个(key重复value还是会覆盖)
  • 安全: 线程不安全

HashMap集合的默认初始化容量是16, 默认加载因子是0.75

  • 初始化容量必须是2的倍数,便于实现散列均匀的效果,从而提高HashMap集合的存取效率
  • 当HashMap集合底层数组的容量达到75%的时候数组按照2的倍数开始扩容
public class HashMapTest01 {
    public static void main(String[] args) {
        // Integer是key,它的hashCode和equals都重写了
        Map<Integer,String> map1 = new HashMap<>();
        map.put(1111, "zhangsan");
        map.put(2222, "zhaoliu");
        map.put(2222, "king"); //key重复的时候value会自动覆盖

        System.out.println(map.size()); // 2

        // 遍历Map集合
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        for(Map.Entry<Integer,String> entry : set){
            // 验证结果:HashMap集合key部分元素:无序不可重复
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        
        Map map2 = new HashMap();
        // HashMap集合允许key为null
        map2.put(null, null);
        System.out.println(map2.size()); // 1

        // key重复的话value会覆盖
        map2.put(null, 100);
        System.out.println(map2.size()); //1

        // 通过key获取value
        System.out.println(map2.get(null)); // 100  
    }
}

Hashtable集合(哈希表)

Hashtable底层是哈希表数据结构,默认初始化容量是11,默认加载因子是0.75

  • 当HashMap集合底层数组的容量达到75%的时候数组按照原容量*2 + 1的机制开始扩容

  • key和value不能为null: 因为其在添加/获取/删除元素时首先就会调用key的hashCode方法或者value的equals方法

  • 安全: 线程安全即类中的方法都带有synchronized关键字,但其对线程的处理导致效率较低,一般使用currentHashMap代替

public class HashtableTest01 {
    public static void main(String[] args) {
        Map map = new Hashtable();
        //map.put(null, "123");
        map.put(100, null);

    }
}

Properties集合(哈希表)

Properties是Hashtable的子类,底层是哈希表数据结构且是线程是安全的,key和value只能存储String类型的字符串

方法名功能
Properties()创建一个 Properties类型的属性类集合
setProperty调用map.put()方法,向集合中存元素
getProperty调用map.get()方法, 通过key获取value
public class PropertiesTest01 {
    public static void main(String[] args) {
        // 创建一个Properties对象
        Properties pro = new Properties();

        // Properties的存元素方法
        pro.setProperty("url", "jdbc:mysql://localhost:3306/bjpowernode");
        pro.setProperty("driver","com.mysql.jdbc.Driver");
        pro.setProperty("username", "root");
        pro.setProperty("password", "123");

        // 通过key获取value
        String url = pro.getProperty("url");
        String driver = pro.getProperty("driver");
        String username = pro.getProperty("username");
        String password = pro.getProperty("password");

        System.out.println(url);
        System.out.println(driver);
        System.out.println(username);
        System.out.println(password);

    }
}

TreeMap(自平衡二叉树)

由于TreeMap集合实现了SortedSet接口,所以集合中存储的键值对的key默认按照字典顺序规则升序排序,也可以通过两种方式手动指定排序规则

  • 第一种方式: 存储的键值对的key需实现Comparable接口,然后重写compareTo方法(返回值决定了元素的排序规则),key重写了该方法后就无需重写equals方法
  • 第二种方式: 构造TreeMap集合时传入一个实现了Comparator接口的比较器对象并重写了compare方法,该比较器对象可以对集合中的元素进行挨个比较

String和Integer以及Date类底层都实现了Comparable接口

方法名功能
TreeMap(Comparator c)在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象

在这里插入图片描述

Comparable可比较接口Comparator比较器接口的应用特点

  • Comparable接口: 适用于比较规则不会发生改变的时候,或者比较规则只有1个的时候
  • Comparator接口: 适用于比较规则之间需要频繁切换,或者比较规则有多个的时候

存储到集合中键值对的key实现Comparable接口并重写compareTo(返回值决定了元素的排序规则)方法,这样集合中的元素就会按照我们指定的规则排序

  • 存储键值对时会先调用key1的compareTo(key2) 方法,返回0表示元素的key相同即覆盖(代替equals方法),不等于0表示按照从大到小或者从小到大顺序排序
public class TreeSetTest05 {
    public static void main(String[] args) {
        TreeMap<Vip> vips = new TreeMap<>();
        vips.add(new Vip("zhangsi", 20));
        vips.add(new Vip("zhangsan", 20));
        vips.add(new Vip("king", 18));
        vips.add(new Vip("soft", 17));
        for(Vip vip : vips){
            System.out.println(vip);
        }
    }
}
// 存储到集合中键值对的key需要实现Comparable接口
class Vip implements Comparable<Vip>{
    String name;
    int age;
    public Vip(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Vip{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    // 在compareTo方法中编写比较的规则,方法的返回值决定了排序的顺序
    @Override
    public int compareTo(Vip v) {
       // 年龄相同时按照名字排序
        if(this.age == v.age){
            // String类型实现了Comparable接口,可以直接调用compareTo方法来完成比较
            return this.name.compareTo(v.name);
        } else {
            // 年龄不一样按照年龄排序
            return this.age - v.age;
        }
    }
}

构造TreeMap集合时传入一个实现了Comparator接口的比较器对象并重写了compare方法,该对象可以对集合中的元素进行挨个比较

  • 创建Comparator接口的实现类对象时可以使用匿名内部类的方式,也可以单独定义一个类继承Comparator接口后再创建对象
public class TreeSetTest06 {
    public static void main(String[] args) {
        // 使用匿名内部类的方式创建比较器对象,也可以单独在这里编写一个类实现Comparator接口
        TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
            @Override
            public int compare(WuGui o1, WuGui o2) {
                return o1.age - o2.age;
            }
        });

        wuGuis.add(new WuGui(1000));
        wuGuis.add(new WuGui(800));
        wuGuis.add(new WuGui(810));

        for(WuGui wuGui : wuGuis){
            System.out.println(wuGui);
        }
    }
}

// 乌龟
class WuGui{
    int age;
    public WuGui(int age){
        this.age = age;
    }
    @Override
    public String toString() {
        return "小乌龟[" +
                "age=" + age +
                ']';
    }
}

// 单独定义一个类继承Comparator接口
class WuGuiComparator implements Comparator<WuGui> {
    @Override
    public int compare(WuGui o1, WuGui o2) {
        // 按照年龄排序
        return o1.age - o2.age;
    }
}

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

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

相关文章

【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)

​ 目录 一、排序的概念及其运用1.1 排序的概念1.2 排序的应用1.3 常见的排序算法 二、常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序2.1.3 直接插入排序和希尔排序的性能对比 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序2.2.3 直接选择排序和堆排序的性能…

会声会影2024旗舰版系统配置要求及格式支持

会声会影2024旗舰版是一款广受欢迎的视频编辑软件&#xff0c;它的最新版本&#xff0c;会声会影2023&#xff0c;已经发布。在这篇文章中&#xff0c;我们将探讨会声会影2024旗舰版系统配置要求及格式支持 会声会影2024是一款专业的视频剪辑软件&#xff0c;能够帮助用户制作高…

写一个宏,交换整数二进制位的奇数位和偶数位,并打印这个新的数

我们已经学过了C语言的宏&#xff0c;我们今天应用宏来交换一个整数的二进制的奇数位和偶数位&#xff0c;并得到这个被交换过的数&#xff0c;我们开始吧&#xff01; 1.问题分析 解题方法&#xff1a;& 和<< 和>>操作符 问题解析&#xff1a;我们这里假设一个…

医保移动支付程序开发

作为公司最苦命的开发&#xff0c;年初接到任务开发医保移动支付程序&#xff08;微信小程序和支付宝小程序&#xff09;&#xff0c;为医疗机构提供线上医保结算。好家伙&#xff0c;我一看解压后资料大于一个G&#xff0c;内心无比的惊慌。 一、技术流程图 图太大了显示不全需…

入门必读:Figma软件的功能和用途一览!

1、Figma软件是做什么的 Figma软件奠定了在线设计工具的形式&#xff0c;产品UI设计功能非常强大&#xff0c;Figma软件基于web操作&#xff0c;无论是macos、windows可以使用这个软件&#xff0c;即使有电脑、浏览器、网络&#xff0c;甚至软件也不需要下载&#xff0c;节省了…

C语言枚举的作用是什么?

我在知乎上看到这个问题&#xff0c;一开始&#xff0c;也有一些疑惑&#xff0c;后面查了一些资料&#xff0c;对于这个问题&#xff0c;简单的说一下我的看法。 枚举有多大 枚举类型到底有多大&#xff0c;占多少空间呢&#xff1f;这个要具体情况具体分析&#xff0c;编译器…

基于ssm框架的公寓租房系统设计与实现

基于ssm框架的公寓租房系统的设计与实现 摘要&#xff1a;在互联网技术的不断发展壮大的背景下,人们生活水平及经济水平也随之得到提上&#xff0c;许多商家都纷纷吧自己的业务重心偏移到网络这个大蛋糕上&#xff0c;为了迎合时代的发展&#xff0c;房屋的出租业务也应该将重…

将测试速度提升数倍!RunnerGo测试平台——您的UI自动化测试利器!

RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度可复用的测试脚本&#xff0c;测试团队无需复杂的代码编写即可开展低代码的自动化…

Windows下Linkis1.5DSS1.1.2本地调试

1 Linkis: 参考&#xff1a; 单机部署 | Apache Linkis技术分享 | 在本地开发调试Linkis的源码 (qq.com)DataSphere Studio1.0本地调试开发指南 - 掘金 (juejin.cn) 1.1 后端编译 参考【后端编译 | Apache Linkis】】 修改linkis模块下pom.xml,将mysql.connetor.scope修改…

LeetCode Hot100 84.柱状图中最大的矩形

题目&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 方法&#xff1a; 代码&#xff1a; class Solution {public int largestRectang…

vue项目中通过vuex管理数据

目录 1.前言&#xff1a; 2.vuex的基础用法&#xff1a; 1.构建与挂载vue 基础模板渲染 构建仓库 2.mutations的使用 1.介绍 ​编辑 2.案列&#xff1a; 3.传参 4.辅助函数mapMutations&#xff1a; 3.module分对象的写法 介绍 建立模块&#xff1a; 访问数据的方…

SPSS生存分析:寿命表分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

PostgreSQL | EXTRACT | 获取时间的年月日字串

EXTRACT EXTRACT 函数是 PostgreSQL 中用于从日期和时间类型中提取特定部分&#xff08;如年、月、日、小时等&#xff09;的函数。 格式 EXTRACT(field FROM source) -- field 参数是要提取的部分&#xff0c;例如 YEAR、MONTH、DAY、HOUR 等。 -- source 参数是包含日期或…

计算机网络高频面试八股文

目录&#xff1a; 网络分层结构三次握手两次握手可以吗&#xff1f;四次挥手第四次挥手为什么要等待2MSL&#xff1f;为什么是四次挥手&#xff1f;TCP有哪些特点&#xff1f;说说TCP报文首部有哪些字段&#xff0c;其作用又分别是什么&#xff1f;TCP和UDP的区别&#xff1f;…

Unity 关于生命周期函数的一些认识

Unity 生命周期函数主要有以下一些&#xff1a; Awake(): 在脚本被加载时调用。用于初始化对象的状态和引用。 OnEnable(): 在脚本组件被启用时调用。在脚本组件被激活时执行一次&#xff0c;以及在脚本组件被重新激活时执行。 Reset(): 在脚本组件被重置时调用。用于重置脚本…

11.27二叉查找树,遍历二叉树,层序(判断是不是完全二叉树),根据遍历序列重构二叉树,递归输入建树(树的定义,结构体细节,typedef)

如果left<right&#xff0c;就表明其之间还有元素&#xff0c;即左右指针重合&#xff0c;区间只有一个元素也被包含其中&#xff1b; left<right,就表明递归过程中&#xff0c;只允许区间有两个及以上的元素&#xff0c;不允许区间只有一个元素&#xff0c;那么对应地&…

Python数据预处理详解

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 数据预处理是数据科学中至关重要的步骤&#xff0c;它包括清洗、转换、归一化等操作&#xff0c;以使数据适合于机器学习模型的使用。Python提供了多种强大的库和工具&#xff0c;能够帮助进行数据预处理。本文将…

中间件安全:JBoss 反序列化命令执行漏洞.(CVE-2017-7504)

中间件安全&#xff1a;JBoss 反序列化命令执行漏洞.&#xff08;CVE-2017-7504&#xff09; JBoss 反序列化漏洞&#xff0c;该漏洞位于 JBoss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中&#xff0c;其 doFilter 方法在没有进行任何安全检查和限制的情况下尝试…

小程序如何进行一键修复

在使用小程序过程中&#xff0c;难免会遇到一些问题&#xff0c;比如程序崩溃、功能异常等等。这时&#xff0c;版本一键修复就显得尤为重要了。下面&#xff0c;我们就来介绍一下小程序如何进行版本一键修复。 一、什么是版本一键修复&#xff1f; 版本一键修复是指在小程序…

YOLOv5算法进阶改进(5)— 主干网络中引入SCConv | 即插即用的空间和通道维度重构卷积

前言:Hello大家好,我是小哥谈。SCConv是一种用于减少特征冗余的卷积神经网络模块。相对于其他流行的SOTA方法,SCConv可以以更低的计算成本获得更高的准确率。它通过在空间和通道维度上进行重构,从而减少了特征图中的冗余信息。这种模块的设计可以提高卷积神经网络的性能。�…