java --- 集合进阶

news2024/12/23 5:54:06

目录

一、单列集合顶层接口 Collection

1.1 基本方法

1.2 Collection 的遍历方式

二、list集合

1.2 ArrayList

 Vector 底层结构

1.3 LinkedList

ArrayList 和 LinkedList 比较

三、set接口

 3.1、Set 接口和常用方法

3.2 HashSet

HashSet 底层机制(HashMap)

 3.3  LinkedHashSet

3.4 TreeSet

四、双列集合Map

 4.1  Map 接口实现类的特点

4.2 Map 接口和常用方法

4.3 Map 接口的三种遍历方法

法一:先获取key的单列集合,再通过key获取vale

法二 获取每个键值对,再getKey ,getValue

法三:lambda表达式,利用Map的forEach方法

4.4  HashMap

4.5 LinkedHashMap

4.6 TreeMap


一、单列集合顶层接口 Collection

1.1 基本方法

常用方法:

Collection是一个接口,我们不能直接创建对象,需要通过他实现类的对象

1.2 Collection 的遍历方式

迭代器遍历

public class collection {
    public static void main(String[] args) {
        Collection<String> c1 = new ArrayList<>(10);
        c1.add("zhangsan");
        c1.add("lisi");
        c1.add("wangwu");
        c1.add("maliu");

        //迭代器的遍历
        Iterator<String> it = c1.iterator();

        while(it.hasNext()){
            String s = it.next();//返回当前元素,并向后移动
            System.out.println(s);
        }
        System.out.println(it.hashCode());
        System.out.println(it);
    }

}

注意点

 Collection接口遍历元素:增强 for 循环

所有的单列集合还有数组都可以通过增强for循环遍历

这里和C++的用法是一样的

//使用增强for
        for(String s : c1){
            System.out.println(s);
        }

使用lambda简化forEach遍历

二、list集合

List相比于Colection最大的改变就是加入了索引

2.1 List接口常用方法:

  1. void add (int index,Object ele) :在index位置插入ele元素;
  2. boolean addAll (int index,Collection eles) :从index位置开始将eles集合中的所有元素添加进来;
  3. Object get (int index) :获取指定index位置的元素;
  4. int indexOf (Object obj) :返回obj在集合中首次出现的位置;
  5. int lastIndexOf (Object obj) :返回obj在集合中末次出现的位置;
  6. Object remove (int index) :移除指定index位置的元素,并返回此元素;
  7. Object set (int index,Object ele) :设置指定index的位置的元素为ele,相当于是替换;
  8. List subList (int fromIndex,int toIndex) :返回从fromIndex到toIndex位置的子集合;
public static void main(String[] args) {
        //向上转型,用List来接收ArrayList
        List l1 = new ArrayList();

//1. void add (int index,Object ele) :在index位置插入ele元素;
        l1.add(1);
        l1.add(2);
        l1.add(3);
        System.out.println(l1);//[1, 2, 3]

//2. boolean addAll (int index,Collection eles) :从index位置开始将eles集合中的所有元素添加进来;
       List l2 = new ArrayList();
       l2.add(10);l2.add(20);
       l1.addAll(l2);
       System.out.println(l1);//[1, 2, 3, 10, 20]

//3. Object get (int index) :获取指定index位置的元素;
        Object o1 = l1.get(0);
        Object o2 = l1.get(3);

//4. int indexOf (Object obj) :返回obj在集合中首次出现的位置;
        int x1 = l1.indexOf(10);
        int x2 = l1.indexOf(1);
//5. int lastIndexOf (Object obj) :返回obj在集合中末次出现的位置;
        int x3 = l1.indexOf(20);
        int x4 = l1.indexOf(2);

//6. Object remove (int index) :移除指定index位置的元素,并返回此元素;
        Object o3 = l1.remove(0);
        System.out.println(l1);

//7. Object set (int index,Object ele) :设置指定index的位置的元素为ele,相当于是替换;
        l1.set(0,666);
        System.out.println(l1);

//8. List subList  (int fromIndex,int toIndex) :返回从fromIndex到toIndex位置的子集合;
        List l3 = l1.subList(0,2);
        System.out.println(l3);
    }

1.2 ArrayList

  • ArrayList 是由数组来实现数据存储的;
  • ArrayList基本等同于 Vector ,除了 ArrayList是线程不安全的,但执行效率高,在多线程的情况下不建议用ArrayList

 Vector 底层结构

  • Vector 底层也是一个对象数组,protected Object[ ] elementData;
  • Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized
  • 在开发中,需要线程同步安全时,考虑使用Vector

底层原理

扩容机制

1.3 LinkedList

  • LinkedList 实现了双向链表和双端队列的特点
  • 可以添加任意元素(元素可以重复),包括null;
  • 线程不安全,没有实现同步
  • LinkedList底层维护了一个双向链表;
  • LinkedList中维护了两个属性first和last分别指向 首节点 和 尾节点;
  • 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终完成双向链表;
  • 所以 LinkedList的元素的添加和删除不是通过数组完成的,相对来说效率较高;
import java.util.Iterator;
import java.util.LinkedList;

public class LinkListCRUD {
    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();

        //增
        linkedList.add(1);//size=0添加一个新节点,首尾指针都指向这个新节点
        linkedList.add(2);//last指向新节点,first还是指向第一个节点,next指向新节点
        linkedList.add(3);
        System.out.println("增后: "+linkedList);

        //删
        linkedList.remove();//默认删除第一个
        System.out.println("删后: "+linkedList);//就是去掉指针

        //改
        linkedList.set(1,999);
        System.out.println("改后: "+linkedList);


        //查
        //get(1) 得到双向链表的第二个对象
        Object o = linkedList.get(1);
        System.out.println(o);//999

        //因为LinkedList是实现了List接口,所以遍历方式:
        Iterator iterator = linkedList.iterator();
        while (iterator.hasNext()) { //快捷输入itit
            Object next =  iterator.next();
            System.out.println(next);
        }
        //还有增强for 和普通for 遍历
    }
}

ArrayList 和 LinkedList 比较

集合底层结构增删的效率改查的效率
ArrayList可变数组较低,数组扩容较高
LinkedList双向链表较高,通过链表追加较低

如何选择 ArrayList 和 LinkedList :

  1. 如果改查的操作较多,选择 ArrayList;
  2. 如果增删的操作较多,选择 LinkedList;
  3. 一般程序中,80%-90%都是查询,因此大部分会使用ArrayList;
  4. 在项目中,灵活选择,可以一个模块用LinkedList,一个模块用ArrayList;

多线程的情况还是考虑 Vector ,因为它是线程安全的

三、set接口

Set 接口介绍:

  1. 无序(添加和取出的顺序不一致),没有索引;
  2. 不允许重复元素,所以最多包含一个null;
  3. JDK API 中Set的常用实现类有:HashSet 和 TreeSet;

 3.1、Set 接口和常用方法

Set 接口的常用方法

  • 和 List 接口一样,Set 接口也是 Collection 的子接口,所以常用方法和Collection接口一样

Set 接口的遍历方式

  • 同 Collection 的遍历一样:
    • 迭代器遍历
    • 增强 for
    • 但 不能用索引 的方式来获取; (因为Set无序
public class Set1 {
    public static void main(String[] args) {
        //Set是接口,不能直接实现,通过他的实现类Hashset来模拟
        //Set不能放重复元素
        //Set遍历的时候无序,和放入顺序不同,但是有固定的顺序
        Set s1 = new HashSet();
        s1.add("xx1");
        s1.add("xx2");
        s1.add("xx3");
        s1.add("xx4");
        System.out.println(s1);

        //迭代器遍历
        Iterator it = s1.iterator();
        while(it.hasNext()){
            Object o1 =it.next();
            System.out.println(o1);
        }
        System.out.println("hhhhhhh");
        //增强for遍历
        for(Object o : s1){
            System.out.println(o);
        }

        //不能索引遍历,且set接口对象没有get()方法
    }
}

3.2 HashSet

  1. HashSet实现了Set接口;
  2. HashSet实际上是HashMap,可以从源码看出;
  3. 可以存放 null 值,但是只能有一个null;
  4. HashSet 不保证元素是有序的,取决于hash后,再确定索引的结果;
  5. 不能有重复元素 / 对象;
import java.util.HashSet;

public class HashSet1 {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        hs.add("zhangsan");
        hs.add("lisi");
        hs.add("wangwu");
        hs.add("maliu");
        System.out.println(hs);
        
        hs.remove("lisi");
    }
}
HashSet 底层机制(HashMap)

HashSet 底层其实是HashMap,HashMap底层是(数组+链表+红黑树)(链地址法

 3.3  LinkedHashSet

  1. LinkedHashSet 是 HashSet 的子类,继承HashSet,实现了Set接口;
  2. LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组+双向链表;
  3. LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的;
  4. LinkedHashSet 不允许添加重复元素;

3.4 TreeSet

TreeSet的独特之处在于它的构造器可以传入比较器,所以TreeSet常用来排序

TreeSet 底层是 TreeMap

public static void main(String[] args) {
        TreeSet t1 = new TreeSet();
        t1.add("aaa");
        t1.add("x");
        t1.add("bb");
        t1.add("hhhh");
        System.out.println(t1);//默认排序:首字母ASCII由小到大
        //[aaa, bb, hhhh, x]

        //如果我们想按字符串大小排序
        //使用TreeSet提供的一个构造器,传入一个比较器(匿名内部类)指定排序规则
        TreeSet t2 = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String)o2).length();
            }
        });
        t2.add("aaa");
        t2.add("x");
        t2.add("bb");
        t2.add("hhhh");
        System.out.println(t2);//按照字符串长度排序
        //[x, bb, aaa, hhhh]
    }

四、双列集合Map

Map为双列集合,Set集合的底层也是Map,只不过有一列是常量所占,只使用到了一列

 4.1  Map 接口实现类的特点

  1. Map 与 Collection 并列存在,用于保存具有映射关系的数据:Key - Value
  2. Map 中的 Key 和 Value 可以是任何引用类型的数据,会封装到 HashMap$Node对象中;
  3. Map中的 Key 不允许重复,原因和 HashSet 一样;
  4. Map 中的 Value 可以重复;
  5. Map 的 Key 可以为 null,value 也可以为 null,但 key 为 null 只能有一个;
  6. 常用 String 类作为 Map 的 key,当然,其他类型也可以,但不常用;
  7. Key 和 Value 之间存在单向一对一关系,即通过指定的 Key 总能找到对应的 Value;

4.2 Map 接口和常用方法

  • put :添加
  • remove : 根据键删除映射关系
  • get : 根据键获取值
  • size : 获取元素个数
  • isEmpty : 判断个数是否为0
  • clear : 清除
  • containsKey : 查找键是否存在
 public static void main(String[] args) {
        Map m1 = new HashMap();
        m1.put("zhangsan",100);
        m1.put("lisi",99);
        m1.put("wangwu",98);
        m1.put("maliu",97);
        System.out.println(m1);//{lisi=99, zhangsan=100, maliu=97, wangwu=98}
        System.out.println(m1.get("zhangsan"));
        System.out.println(m1.get("maliu"));

        System.out.println(m1.size());

        System.out.println(m1.isEmpty());

        System.out.println(m1.containsKey("wangwu"));

        m1.clear();
        System.out.println(m1);
    }

4.3 Map 接口的三种遍历方法

法一:先获取key的单列集合,再通过key获取vale

keySet()

public class Map遍历 {
    public static void main(String[] args) {
        Map<String,Integer> m1 = new HashMap();
        m1.put("zhangsan",100);
        m1.put("lisi",99);
        m1.put("wangwu",98);
        m1.put("maliu",97);

        //方法一:先获取键(先获取key的单列集合),再通过键获取值
        //1.增强for
        Set<String> keys = m1.keySet();

        for(String k : keys){
            System.out.println(k + " - "+m1.get(k));
        }
        System.out.println();
        //2.迭代器
        Iterator it1 = keys.iterator();
        while(it1.hasNext()){
            Object s = it1.next();
            System.out.println(s+" - "+m1.get(s));
        }
        System.out.println();
        //3.lambda表达式
        keys.forEach(str ->{
            System.out.println(str + " - "+m1.get(str));
        });

    }
}

法二 获取每个键值对,再getKey ,getValue

entrySet()

public class map遍历02_entrySet {
    public static void main(String[] args) {
        Map<String,Integer> m1 = new HashMap();
        m1.put("zhangsan",100);
        m1.put("lisi",99);
        m1.put("wangwu",98);
        m1.put("maliu",97);

        Set<Map.Entry<String,Integer>> setentry = m1.entrySet();
        //接下来就是三种遍历,和keySet一样的
        for(Map.Entry<String,Integer> e1 : setentry){
            String k = e1.getKey();
            Integer v = e1.getValue();
            System.out.println(k+" - "+v);
        }
        System.out.println();
        //迭代器
        Iterator<Map.Entry<String,Integer>> it = setentry.iterator();
        while(it.hasNext()){
            Map.Entry<String,Integer> tmp = it.next();
            String k = tmp.getKey();
            Integer v = tmp.getValue();
            System.out.println(k+" - "+v);
        }
        System.out.println();
        //lamdba表达式
        setentry.forEach(tmp ->{
            String k = tmp.getKey();
            Integer v = tmp.getValue();
            System.out.println(k+" - "+v);
        });
    }
}

法三:lambda表达式,利用Map的forEach方法

public class Map遍历03_lambda {
    public static void main(String[] args) {
        Map<String,Integer> m1 = new HashMap();
        m1.put("zhangsan",100);
        m1.put("lisi",99);
        m1.put("wangwu",98);
        m1.put("maliu",97);

        //利用forEach可以直接进行遍历
        m1.forEach(new BiConsumer<String, Integer>() {
            @Override
            public void accept(String k, Integer v) {
                System.out.println(k+" - "+v);
            }
        });
        System.out.println();
        //lambda表达式改进
        m1.forEach((k,v)->{
            System.out.println(k+" - "+v);
        });
    }
}

4.4  HashMap

  1. Map 接口的常用实现类:HashMap、Hashtable、Properties;
  2. HashMap 是 Map 接口使用频率最高的实现类;
  3. HashMap 是以 key - value 对的形式来存储的;
  4. key 不能重复添加,但value可以,都允许使用null;
  5. 如果添加相同的 key,则会覆盖原来的 key - value,等同于修改;
  6. 与 HashSet一样,不保证映射的顺序,因为底层是以哈希表的方式来存储的;
  7. HashMap 没有实现同步,所以线程不安全;

HashMap的用法以及扩容机制和C++中的unorded_map是一样的

利用HashMap来统计80个同学对四个景点的意向

public class HashMap01 {
    public static void main(String[] args) {
        //1.先来定义几个景点
        String[] s = new String[]{"A","B","C","D"};
        //2.定义一个HashMap
        HashMap<String,Integer> hm = new HashMap<>();
        //3.用随机数模拟同学们的投票
        Random r = new Random();
        for(int i=0;i<80;++i){
            int index = r.nextInt(s.length);
            if(hm.containsKey(s[index])){
                //已经插入过了
                int count = hm.get(s[index]);
                count++;
                hm.put(s[index],count);
            }else{
                //第一次插入
                hm.put(s[index],1);
            }
        }
        //4.将HashMap的结果输出
        System.out.println(hm);

        //5.遍历求最多的那个
        int res = 0;
        Set<String> entry = hm.keySet();
        for(String str : entry){
            int tmp = hm.get(str);
            res = Math.max(res,tmp);
        }
        System.out.println(res);

        System.out.println();
        Set<Map.Entry<String, Integer>> entries = hm.entrySet();
        for(Map.Entry<String,Integer> e : entries){
            res = Math.max(res,e.getValue());
        }
        System.out.println(res);
    }
}

4.5 LinkedHashMap

4.6 TreeMap

这和C++当中的Map是几乎一样的。

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

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

相关文章

虚拟机Linux(Centos7)安装Docker

如果没有安装虚拟机的&#xff0c;可以参考这篇VMware虚拟机安装Linux操作系统&#xff08;CentOS7&#xff09; 文章目录 0.安装Docker1.CentOS安装Docker1.1.卸载&#xff08;可选&#xff09;如何看自己的虚拟机上是否安装过docker&#xff1f; 1.2.安装docker1.3.启动docke…

pytest之allure测试报告02:allure具体使用方法

一、allure包含的方法 二、allure使用教程 &#xff08;1&#xff09;用例中写入allure方法 allure.epic("数据进制项目epic") allure.feature("手机号模块feature") class TestMobile:allure.story("杭州的手机号story")allure.title("测…

多层记忆增强外观-运动对齐框架用于视频异常检测 论文阅读

MULTI-LEVEL MEMORY-AUGMENTED APPEARANCE-MOTION CORRESPONDENCE FRAMEWORK FOR VIDEO ANOMALY DETECTION 论文阅读 摘要1.介绍2.方法2.1外观和运动对其建模2.2.记忆引导抑制模块2.3. Training Loss2.4. Anomaly Detection 3.实验与结果4.结论 论文标题&#xff1a;MULTI-LEVE…

重磅!大模型(LLMs)排行榜清单发布!

目前&#xff0c;人工智能领域呈现出一片蓬勃发展的景象&#xff0c;大型模型成为了激发这一繁荣的关键引擎。 国内不仅涌现了众多大模型&#xff0c;而且它们的发展速度之快令人瞩目。这种全面拥抱大型模型的态势为整个人工智能生态系统赋予了新的活力&#xff0c;让我们对国…

栈——OJ题

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、最小栈1、题目讲解2、思路讲解3、代码实现 二、栈的压入、弹出序列1、题目讲解2、思路讲解…

CCD相机为什么需要积分球均匀光源

积分球内腔是一个具备高漫反射特性的收光球&#xff0c;其内部中空、内球面均匀地涂有漫反射材料&#xff0c;具有匀光与混光的作用&#xff0c;因此常常被用来做收光的均光球。由于光源性能等因素的影响&#xff0c;可能导致出射光线带偏振方向、出光不均匀&#xff0c;使用积…

Windows11环境下配置深度学习环境(Pytorch)

目录 1. 下载安装Miniconda2. 新建Python3.9虚拟环境3. 下载英伟达驱动4. 安装CUDA版Pytorch5. CPU版本pytorch安装 1. 下载安装Miniconda 下载安装包&#xff1a;镜像文件地址 将Miniconda相关路径添加至系统变量的路径中。 打开Anaconda Powershell Prompt&#xff0c;输入…

【C++学习————引用】

【C学习——————引用】 欢迎阅读新一期的c模块————引用 ✒️个人主页&#xff1a;-Joker- &#x1f3f7;️专栏&#xff1a;C &#x1f4dc;代码仓库&#xff1a;c_code &#x1f339;&#x1f339;欢迎大佬们的阅读和三连关注&#xff0c;顺着评论回访&#x1f339;&a…

秋招上岸记录咕咕咕了。

思考了一下&#xff0c;感觉并没有单独写这样一篇博客的必要。 能够写出来的&#xff0c;一些可能会对人有帮助的东西都做进了视频里面&#xff0c;未来会在blbl发布&#xff0c;目前剪辑正在施工中&#xff08;&#xff1f;&#xff09; 另外就是&#xff0c;那个视频里面使…

Win11 跑通tensorRT

cuda_12.3.1_546.12_windows TensorRT-8.6.1.6.Windows10.x86_64.cuda-12.0 cudnn-windows-x86_64-8.9.7.29_cuda12-archive 准备 1.安装cuda&#xff0c;成功之后文件夹如下图所示 2.下载cudnn&#xff0c;把cudnn对应的文件放在cuda里面 3.安装vs 4.安装对应cuda版本的te…

DevOps常用工具全家桶,实现高效运维和交付

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…

Linux c++开发-06-使用Linux API 进行文件的读写

先简单的介绍一下open,read,write 先用open接口去打开文件&#xff0c;flag表示打开文件的权限不同。 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);示例 结果&#xff1a;

基于AT89C51单片机的LED点阵显示屏设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; [[https://download.csdn.net/download/qq_64505944/88637464?spm1001.2014.3001.5503]] **[源码获取] B 源码仿真图课程设计50 工程实训&#xff08;三&#xff09;课题设计 班级&#xff1a; …

FPGA — Vivado下ILA(逻辑分析仪)详细使用方法

使用软件&#xff1a; Vivado 开发板&#xff1a; EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA 使用程序&#xff1a;按键案例 ILA详细使用方法 一、ILA简介二、ILA的使用方法方法1 — 使用IP核创建ILA调试环境创建ILA IP核 方法二 — 使用 Debug 标记创建 ILA对需观察信…

使用IDEA创建springboot依赖下载很慢,解决方法

显示一直在resolving dependencies&#xff0c;速度很慢 原因&#xff1a;maven会使用远程仓库来加载依赖&#xff0c;是一个国外的网站&#xff0c;所以会很慢。应该使用阿里云的镜像&#xff0c;这样速度会提升很多。 步骤&#xff1a;1.右击pom.xml&#xff0c;选择"m…

DevEco Studio 项目鸿蒙(HarmonyOS)多语言

DevEco Studio 项目鸿蒙&#xff08;HarmonyOS&#xff09;多语言 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、多语言 新版本IDE可以创建多语言的文件夹&#xff0c;在entry->src->main->resources下&#xff0c;修…

图像识别完整项目之Swin-Transformer,从获取关键词数据集到训练的完整过程

0. 前言 图像分类的大部分经典神经网络已经全部介绍完&#xff0c;并且已经作了测试 代码已经全部上传到资源&#xff0c;根据文章名或者关键词搜索即可 LeNet &#xff1a;pytorch 搭建 LeNet 网络对 CIFAR-10 图片分类 AlexNet &#xff1a; pytorch 搭建AlexNet 对花进行分…

为什么Apache Doris适合做大数据的复杂计算,MySQL不适合?

为什么Apache Doris适合做大数据的复杂计算&#xff0c;MySQL不适合&#xff1f; 一、背景说明二、DB架构差异三、数据结构差异四、存储结构差异五、总结 一、背景说明 经常有小伙伴发出这类直击灵魂的疑问&#xff1a; Q&#xff1a;“为什么Apache Doris适合做大数据的复杂计…

相机倾斜棋盘格标定全记录 vs200+opencv安装

论文参考是这个 Geiger A, Moosmann F, Car , et al. Automatic camera and range sensor calibration using a single shot[C]//Robotics and Automation (ICRA), 2012 IEEE International Conference on. IEEE, 2012: 3936-3943. 代码是这个github 花了一上午配好了c环境。。…

Activiti工作流框架学习笔记(一)之通用数据表详细介绍

文/朱季谦 Activiti工作流引擎自带了一套数据库表&#xff0c;这里面有一个需要注意的地方&#xff1a; 低于5.6.4的MySQL版本不支持时间戳或毫秒级的日期。更糟糕的是&#xff0c;某些版本在尝试创建此类列时将引发异常&#xff0c;而其他版本则不会。执行自动创建/升级时&a…