Java:集合(List、Map、Set)

文章目录

  • 1. Collection集合
    • 1-1. 迭代器遍历方式
    • 1-2. 通过for循环进行遍历
    • 1-3. forEach遍历
  • 2. List集合
    • 2-1. ArrayList底层实现原理
    • 2-2. LinkedList底层实现原理
  • 3. Set集合
    • 3-1. HashSet 底层实现
    • 3-2. LinkedHashSet 底层实现
    • 3-3. TreeSet
  • 4. Collection集合->总结
  • 5. Map集合
    • 5-1. 通过键找值-进行遍历
    • 5-2. 键值对进行遍历
    • 5-3. 通过Lambda表达式进行遍历
    • 5-4. HashMap 底层实现
    • 5-5. LinkedHashMap 底层原理
    • 5-6. TreeMap 底层原理

1. Collection集合

本身为一个接口。
在这里插入图片描述

包括List、Set集合两种。其中List集合添加的元素有序、可重复、有索引,下面有两个实现类,分别为ArrayList、LinkedList。而Set集合添加的元素是无序的、不重复的、无索引的。它的实现类有HashSet、LinkedHashSet、TreeSet,需要注意的是LinkedHashSet中的元素是有序的,TreeSet中的元素是按照大小默认升序进行排序的。

1-1. 迭代器遍历方式

package jh_study;


import java.util.*;

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

        Collection<String> c = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            c.add(String.valueOf(i+1));
        }
        Iterator<String> iterator = c.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

通过集合对象".iterator()"获取其迭代器对象,然后通过“迭代器对象.hasNext()”方法来判断是否已经到末尾;没有到末尾的话,可以通过“迭代器对象.next()”获取对应的元素值,不过获取到元素值之后,其对应的索引(或者指针节点)会指向下一个位置

1-2. 通过for循环进行遍历

package jh_study;


import java.util.*;

public class JHStudy {

    public static void main(String[] args) {

        Collection<String> c = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            c.add(String.valueOf(i+1));
        }
        for (String s : c) {
            System.out.println(s);
        }
    }
}

这种方式遍历集合,本质上就是迭代器遍历集合的简化写法。

1-3. forEach遍历

在这里插入图片描述

package jh_study;


import java.util.*;
import java.util.function.Consumer;

public class JHStudy {

    public static void main(String[] args) {

        Collection<String> c = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            c.add(String.valueOf(i+1));
        }
        // 匿名内部类写法
        c.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        // 简化
        c.forEach((e)->{
            System.out.println(e);
        });
        // 再简化
        c.forEach((e)-> System.out.println(e));
        // 再简化
        c.forEach(System.out::println);
    }
}

Collection是一个接口,因此实现了该接口对应的类都具备其下的方法。

2. List集合

遍历元素方式除了上述三种之外,还可以通过下标索引进行遍历,当然需要使用到for循环

package jh_study;

import java.util.*;

public class JHStudy {

    public static void main(String[] args) {

        List<Integer> l = new ArrayList<>();
        l.add(12);
        l.add(0);
        for (int i = 0; i < l.size(); i++) {
            System.out.println(l.get(i));
        }
    }
}

2-1. ArrayList底层实现原理

底层实现是基于数组实现的,查看源代码可以发现。
在这里插入图片描述
在这里插入图片描述
根据索引查询速度快(查询数据通过地址值和索引进行定位,查询任意数据耗时相同),删除效率低(可能需要把后面很多的数据进行前移),添加效率低(可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组扩容。)

ArrayList底层实现原理:
1.利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组;
2.添加第一个元素时,底层会创建一个新的长度为10的数组;
在这里插入图片描述
在这里插入图片描述
3.存满时,会扩容1.5倍;
在这里插入图片描述
在这里插入图片描述

如果一次添加多个元素,1.5倍还放不下,则新创建的数组的长度以实际为准;
在这里插入图片描述

2-2. LinkedList底层实现原理

底层实现是双向链表。
在这里插入图片描述
在这里插入图片描述
LinkedList的应用场景:实现栈(后进先出)、队列(先进先出)。

3. Set集合

正如上述所说,常见的set集合类型有HashSet、LinkedHashSet、TreeSet。其中,HashSet特点为无序、不重复、无索引;LinkedHashSet特点为有序、不重复、无索引;TreeSet特点为升序、不重复、无索引。

package jh_study;

import java.util.*;

public class JHStudy {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> set1 = new LinkedHashSet<>();
        Set<Integer> set2 = new TreeSet<>();

        System.out.println("HashSet集合");
        set.add(333);
        set.add(2222);
        set.add(1111);
        set.add(2333);
        System.out.println(set);

        System.out.println("LinkedHashSet集合");
        set1.add(333);
        set1.add(2222);
        set1.add(1111);
        set1.add(2333);
        System.out.println(set1);

        System.out.println("TreeSet集合");
        set2.add(333);
        set2.add(2222);
        set2.add(1111);
        set2.add(2333);
        System.out.println(set2);

    }
}

在这里插入图片描述

3-1. HashSet 底层实现

关于hash值,就是一个int类型的数值,Java中每一个对象都有一个hash值;Java中所有的对象,都可以通过调用Object类提供的hashCode方法,返回该对象自己的hash值。
hash值的特点:同一个对象多次调用hashCode方法返回的hash值是相同的;不同对象,它们的hash值一般不相同,但是也有可能相同(hash碰撞)。
在这里插入图片描述
HashSet底层原理:是基于hash表实现的,hash表是一种增删改查数据性能都较好的数据结构。jdk8之前hash表的实现是基于数组+链表实现的;jdk8之后hash表的实现是基于数组+链表+红黑树实现的。
jdk8之前的哈希表底层实现为:创建一个默认长度为16的数组,默认加载因子为0.75(也就是当长度为12时,会进行扩容操作,原数组中的元素会添加到新数组当中去);使用元素的哈希值对数组长度求余计算出应存入的位置;判断当前位置是否为null,如果为null直接存入,如果不为null,表示该位置有元素,则调用equals方法进行比较,相等,则不存,不相等,则存入数组,也就是在数组对应的位置上创建链表,元素存入到链表中进行存储。在jdk8之后,当链表长度超过8,并且数组长度大于或等于64时,自动将链表转换为红黑树。
在这里插入图片描述
jdk8之前的Hash表结构。
在这里插入图片描述
jdk8之后的Hash表结构。
如果在HashSet中有两个内容相同但是它们hash值不同,此时如果我们想去重的话,需要重写其hashCode和equals方法。

package jh_study;


import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class User{
    private String name;
    private Integer age;

    public User(String name, Integer 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;
        User user = (User) o;
        return Objects.equals(name, user.name) && Objects.equals(age, user.age);
    }

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

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


public class JHStudy2 {


    public static void main(String[] args) {

        Set<User> users = new HashSet<>();

        users.add(new User("张三",20));
        users.add(new User("张三",20));

        System.out.println(users);
    }
}

在这里插入图片描述

3-2. LinkedHashSet 底层实现

LinkedHashSet为HashSet的子类,底层实现依旧是基于哈希表(数组、链表、红黑树)实现的。但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。
在这里插入图片描述

3-3. TreeSet

在这里插入图片描述

底层实现基于红黑树实现的升序排序(默认情况下),特点是不重复、无索引、可排序(默认升序排序)。如果在TreeSet中存储的数类型为自定义类型(比如Student),此时如果打印输出结果会报错,因此TreeSet类型并不知道通过Student那个属性进行计较,此时可以在Student类下,让其实现Comparable接口,并重写方法compareTo;当然,也可以直接在定义TreeSet类型的变量时,给上参数new Comparator比较器对象,让其实现方法compare。

package jh_study;

import java.util.*;

public class JHStudy3 {


    public static void main(String[] args) {

        Set<Integer> set = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        // 简化写法
        /*Set<Integer> set = new TreeSet<>((a,b)->{
            return b - a;
        });*/


        set.add(3);
        set.add(1);
        set.add(2);
        System.out.println(set);

    }
}

在这里插入图片描述

如果上述两种都设置了,类对象实现了Comparable接口,定义TreeSet变量时指定了比较器,那么采用就近原则上那个(也就是比较器)来进行排序的。

4. Collection集合->总结

  1. 如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据,可以采用ArrayList集合类型(底层实现基于数组,特点是有序、可重复、有索引);
  2. 如果希望记住元素的添加顺序,且增删首尾数据的情况较多,可以采用LinkedList集合类型(底层实现基于双链表,特点是有序、可重复、有索引);
  3. 如果不在意元素顺序,也没有重复元素需要存储,只希望增删查改都快,可以采用HashSet集合类型;(底层实现基于哈希表,特点是无序、不重复、无索引
  4. 如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快,可以采用LinkedHashSet集合类型(底层实现基于哈希表和双链表,特点为有序、不重复、无索引);
  5. 如果要对元素进行排序,也没有重复元素需要存储,且希望增删改查都快,可以采用TreeSet集合类型(底层实现基于红黑树,特点为升序、不重复、无索引);

在这里插入图片描述

5. Map集合

键值对集合,键不能重复,值可以重复。
常见的比如HashMap(无序、不重复、无索引)、TreeMap(有序、不重复、无索引)、LinkedHashMap(按照大小默认升序排序,不重复,无索引)。

package jh_study;

import java.util.*;

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

        Map<String, String> map = new HashMap<>();
        map.put(null,null);
        map.put("张三","男");
        map.put("李四","女");
        map.put("嘻嘻1","MyDream");
        System.out.println(map);
        // {null=null, 李四=女, 张三=男, 嘻嘻1=MyDream}
        System.out.println(map.get("张三"));
        //男 ,获取键对应的值
        System.out.println(map.get("赵六"));
        // null ,不存在的键
        System.out.println(map.containsKey("李四"));
        // 判断是否存在某个键 true
        // map.clear();
        // 清空map中的数据
        Set<String> set = map.keySet();
        System.out.println(set);
        // 获取所有的键 [null, 李四, 张三, 嘻嘻1]
        System.out.println(map.isEmpty());
        // 判断map是否为空 false
        System.out.println(map.values());
        // 获取map中所有的值 [null, 女, 男, MyDream]
        System.out.println(map.size());
        // 获取map的长度 4
        System.out.println(map.remove("张三"));
        // 删除某个键,并返回这个键对应的值 男

    }
}

5-1. 通过键找值-进行遍历

通过Map对象的 keySet() 方法获取对应的键集合,然后通过遍历键集合来获取对应的值。

package jh_study;


import java.util.*;

public class JHStudy4 {
    
    public static void main(String[] args) {
        
        Map<String, String> map = new HashMap<>();
        map.put(null,null);
        map.put("张三","男");
        map.put("李四","女");
        map.put("嘻嘻1","MyDream");
        map.put("赵六","man");
        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key+"->"+map.get(key));
        }
    }
}

在这里插入图片描述

5-2. 键值对进行遍历

通过Map对象的 entrySet() 方法获取键值对集合,然后对这个集合进行遍历即可。

package jh_study;


import java.util.*;

public class JHStudy4 {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put(null,null);
        map.put("张三","男");
        map.put("李四","女");
        map.put("嘻嘻1","MyDream");
        map.put("赵六","man");
        Set<Map.Entry<String, String>> set = map.entrySet();
        for (Map.Entry<String, String> entry : set) {
            System.out.println(entry.getKey()+"=>"+entry.getValue());
        }
    }
}

5-3. 通过Lambda表达式进行遍历

package jh_study;


import java.util.*;
import java.util.function.BiConsumer;

public class JHStudy4 {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put(null,null);
        map.put("张三","男");
        map.put("李四","女");
        map.put("嘻嘻1","MyDream");
        map.put("赵六","man");
        map.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String s, String s2) {
                System.out.println(s+" "+s2);
            }
        });
        // 简化
        map.forEach((k,v)-> System.out.println(k+" "+v));
    }
}

在这里插入图片描述

5-4. HashMap 底层实现

HashMap和HashSet的底层实现原理都是一样的,都是基于哈希表实现的。在JDK8之前,其哈希表基于数组+链表;JDK8之后,其哈希表基于数组+链表+红黑树实现。
在这里插入图片描述

5-5. LinkedHashMap 底层原理

LinkedHashMap 和 LinkedHashSet的底层原理是一样的。
在这里插入图片描述
在这里插入图片描述

5-6. TreeMap 底层原理

TreeMap和TreeSet的底层实现原理都是一样的。
在这里插入图片描述
如果要对数据进行排序,也有两种方式,和TreeSet一样,参考代码如下:
方法1:让需要排序的对象数据实现Comparable即可,并重写方法compareTo。

package jh_study;


import java.util.*;

public class JHStudy4 {

    public static void main(String[] args) {



        Map<User4, Integer> map = new TreeMap<>();
        map.put(new User4("张三",23),0);
        map.put(new User4("李四",12),1);
        map.put(new User4("王五",10),2);
        map.put(new User4("赵六",25),3);

        System.out.println(map);

    }
}



class User4 implements Comparable<User4>{
    String name;
    Integer age;

    public User4(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

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

    @Override
    public int compareTo(User4 o) {
        return o.age - this.age;
    }
}

在这里插入图片描述
方法2:通过比较器,参考代码如下:

package jh_study;


import java.util.*;

public class JHStudy4 {

    public static void main(String[] args) {



        Map<User4, Integer> map = new TreeMap<>(new Comparator<User4>() {
            @Override
            public int compare(User4 o1, User4 o2) {
                return o1.age-o2.age;
            }
        });
        map.put(new User4("张三",23),0);
        map.put(new User4("李四",12),1);
        map.put(new User4("王五",10),2);
        map.put(new User4("赵六",25),3);

        System.out.println(map);

    }
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

私有云dbPaaS为何被Gartner技术成熟度曲线标记为“废弃”?

当云计算席卷而来&#xff0c;基于云基础设施的数据库部署也改变了数据库。在传统的私有化部署&#xff08;On-premises&#xff09;和公有云部署&#xff08;Public Cloud&#xff09;之间&#xff0c;不断融合的混合IT&#xff08;Mixed IT&#xff09;形式成为最常见的企业级…

ElementPlus Table 表格实现可编辑单元格

通过基础的Table表格来实现单元格内容的可编辑 1.首先定位到需要编辑的列&#xff0c;替换el-table-column <el-table-column label"Editable Column" width"300"><template #default"{ row, column, $index }"><el-inputsize&qu…

《数据结构》(408代码题)

2009 单链表&#xff08;双指针&#xff09; 分析&#xff1a;首先呢&#xff0c;给我们的数据结构是一个带有表头结点的单链表&#xff0c;也不允许我们改变链表的结构。链表的长度不是直接给出的啊&#xff0c;所以这个倒数也很棘手。那我们该如何解决这个“k”呢&#xff0c…

Qt控件的盒子模型,了解边距边线和内容区

这篇专门讲讲一个控件在绘制时的视觉样式。我们平常在对控件设置样式时&#xff0c;需要设置控件的一些外边距&#xff0c;内边距&#xff0c;边线&#xff0c;还有文字内容&#xff0c;贴上图片等。那么对于一个控件&#xff0c;到底怎么实现这些设置的呢&#xff1f; 先看下面…

第十二课 Unity 内存优化_内存工具篇(Memory)详解

内存&#xff08;Memory&#xff09; unity 内存部分也是优化过程中非常重要的一个环节&#xff0c;也会影像渲染过程中的同步等待与带宽问题。因此内存的优化也可能会给我们渲染开销带来精简&#xff0c;今天我们先来了解unity中的内存与使用到的内存工具。 Unity中的内存 托…

windows mysql5.7设置慢查询参数

如果没有my.ini,可以复制一份my-default.ini改个名字就可以。 注意重启mysql服务 mysql5.7 直接在配置文件my.ini 中写如下配置 log_slow_admin_statements ON log_slow_slave_statements ON slow_query_log 1 //开启慢查询 &#xff08;很多博客说on off ,我本机my…

STM32F407+LAN8720A +LWIP +FreeRTOS ping通

使用STM32CUBEIDE自带的 LWIP和FreeROTS 版本说明STM32CUBEIDE 操作如下1. 配置RCC/SYS2. 配置ETH/USART3. 配置EHT_RESET/LED4. 配置FreeRTOS5. 配置LWIP6. 配置时钟7. 生成单独的源文件和头文件,并生成代码8. printf重定义9. ethernetif.c添加lan8720a复位10. MY_LWIP_Init …

【电脑技巧】将键盘的方向键映射为alt+i、k、j、l

最近感觉方向键太远了&#xff0c;想找个方法修改键盘映射&#xff0c;有几种方式可以实现 使用powertoys的键盘映射&#xff08;软件太大了&#xff0c;只为键盘映射不值得下这个&#xff09;使用autohotkey&#xff08;通过脚本的方式&#xff0c;可以打包成exe文件&#xf…

物联网中的数据收集:MQTT实现的比较

本篇论文的标题是《Data collection in IoT: A comparison of MQTT implementations》&#xff0c;中文可以翻译为《物联网中的数据收集&#xff1a;MQTT实现的比较》。论文由Erik Gustafsson和Ruben Jarefors撰写&#xff0c;导师是Jalal Maleki&#xff0c;评审员是Rita Kovo…

【开源】使用环信UIKit for uniapp 做一个IM即时聊天应用

环信单群聊 UIKit 是基于环信即时通讯云 IM SDK 开发的一款即时通讯 UI 组件库&#xff0c;提供各种组件实现会话列表、聊天界面、联系人列表及后续界面等功能&#xff0c;帮助开发者根据实际业务需求快速搭建包含 UI 界面的即时通讯应用。 本文教大家使用环信 uniapp UIKit 快…

人工智能增强的音频和聊天协作服务

论文标题&#xff1a;AI-enabled Audio and Chat Collaboration Services 中文标题&#xff1a;人工智能增强的音频和聊天协作服务 作者信息&#xff1a; Emil P. Andersen, Norwegian Defence Research Establishment (FFI), Kjeller, NorwayJesper R. Goksr, Sindre E. Ha…

突破时间与空间限制的富媒体百宝箱——智能工具箱:让云上内容生产更easy

“这是你的同款日常吗&#xff1f;老是在赶deadline&#xff0c;苦练PS还未出师&#xff0c;premiere、达芬奇真的好难&#xff0c;学python脑容量确实不够~打工人太难了~~” 来试试智能工具箱吧&#xff01;即来即用&#xff0c;一键实现办公自由。图片工具、视频工具、音频工…

基于python绘制数据表(下)

绘制雷达图-源码 from openpyxl import Workbook from openpyxl.chart import RadarChart, Reference# 创建工作薄 wb Workbook() # 选定工作表 ws wb.active# 准备数据 rows [[Mouth, Bulbs, Seeds, Flowers, Trees],[Jan, 0, 2200, 500, 0],[Feb, 0, 2000, 560, 0],[Mar,…

PT2044A 单触控单输出IC

1 产品概述 ● PT2044A 是一款单通道触摸检测芯片。该芯片内建稳压电路&#xff0c;提供稳定电压给触摸感应电路使用。同时内部集成高效完善的触摸检测算法&#xff0c;使得芯片具有稳定的触摸检测效果。该芯片专为取代传统按键而设计&#xff0c;具有宽工作电压与低功耗的特性…

华为HarmonyOS实现跨多个子系统融合的场景化服务 -- 7 地图选点Button

场景介绍 本章节将向您介绍如何使用地图选点Button功能&#xff0c;开发者可调用Button组件拉起Map Kit的地图选点页面&#xff0c;用户在地图中选择位置后&#xff0c;位置相关信息返回Button界面。 说明 该场景暂不支持2in1设备。 前提条件 参见开发准备。 效果图展示 …

MVC流程分析

DisaptcherServlet本质是servlet&#xff0c;执行init()方法&#xff0c;自启动底层执行代码&#xff0c; 作用&#xff1a; 1、读取springmvc配置文件&#xff0c;创建Controller对象&#xff0c;放入容器中&#xff0c;map<"id",对象> 2、接收用户请求&#…

路径规划之启发式算法之十六:和声搜索算法(Harmony Search, HS)

和声搜索算法(Harmony Search, HS)是一种新兴的启发式全局搜索算法,是一种模拟音乐家即兴演奏过程的群体智能优化算法。这种算法由Zong Woo Geem等人在2001年提出,灵感来源于音乐家在寻找和声时的创造性思维过程。HS算法通过模拟音乐家演奏音乐时的选择过程来寻找问题的最优…

游戏引擎学习第45天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 我们刚刚开始研究运动方程&#xff0c;展示了如何处理当人物遇到障碍物时的情况。有一种版本是角色会从障碍物上反弹&#xff0c;而另一版本是角色会完全停下来。这种方式感觉不太自然&#xff0c;因为在游戏中&#xff0c;…

[2015~2024]SmartMediaKit音视频直播技术演进之路

技术背景 2015年&#xff0c;因应急指挥项目需求&#xff0c;我们实现了RTMP推送音视频采集推送&#xff08;采集摄像头和麦克风数据&#xff09;模块&#xff0c;在我们做好了RTMP推送模块后&#xff0c;苦于没有一个满足我们毫秒级延迟诉求的RTMP播放器&#xff0c;于是第一…

C语言实现八大排序算法

目录 1.插入排序 1.1 直接插入排序 1.2 希尔排序 2. 选择排序 2.1 直接选择排序 2.2 堆排序 *TopK问题&#xff1a; 3. 交换排序 3.1 冒泡排序 3.2 快速排序 1. Hoare版本 2. 挖坑法 3. 前后指针法 4. 快速排序优化 5. 非递归快速排序 4.归并排序 1.递归式归并…