Java-集合/容器

news2024/12/28 4:09:39

集合的概念

当我们需要保存一组一样(类型相同)的元素的时候,我们应该使用一个容器来存储,数组就是这样一个容器。

数组的特点:     

数组是一组数据类型相同的元素集合;

创建数组时,必须给定长度,而且一旦创建长度不能改变;

一旦数组装满元素,就需要创建一个新的数组,将元素复制过去;

数组的局限:

如果装满了,就需要数组复制;

当我们需要从数组中删除或添加一个元素,需要移动后面的元素;

集合的作用:

在开发实践中,我们需要一些能够动态增长长度的容器来保存我们的数据,java中为了解决数据存储单一的情况,java中就提供了不同结构的集合类,可以让我们根据不同的场景进行数据存储的选择,如Java中提供了 数组实现的集合,链表实现的集合,哈希结构,树结构等。

分类

单列集合:一次放进去一个值 ( 对象 )

Collection接口:定义了单列集合共有的方法,其子接口Set和List分别定义了存储方式

List:可以有重复元素

Set:不可以有重复元素

双列集合: 键    值

集合API

集合体系概述: Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中。

List 接口及实现类

概念:List继承了Collection接口,有三个实现的类,分别是:

ArrayList       数组列表

LinkedList     链表列表

Vector            数组列表 (是线程安全的)

1.  ArrayList

底层有一个数组,可以动态扩展数组长度,并提供了一系列方法操作。

特点: 查询快,在中间增加 / 删除慢

注意:集合容器类中默认可以添加Object类型,但是一般建议一个集合对象只保存同一种类型,若保存多个类型后期处理时涉及类型转换问题;所以我们可以通过泛型来加以控制。


泛型:声明类型时可以自定义参数类型
           ArraysList  <E>
ArrayList的常用方法:

ArrayList<String> arrayList = new ArrayList();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add(3,"a");
       
        arrayList.remove("a");  //根据内容删除匹配的第一个元素,返回值为boolean
        arrayList.remove(1);    //删除并返回指定位置的元素
        arrayList.get(1);         //获取指定位置的元素
        arrayList.set(1,"X");     //替换并返回指定位置的元素
        arrayList.clear();        //清空集合中的元素
        arrayList.isEmpty();      //判断集合元素是否为空
        arrayList.contains("c");  //判断是否包含指定元素
        arrayList.size();         //返回集合中元素个数

2.  LinkedList

底层是一个链表结构,查询效率低,但增加 / 删除元素快

LinkedList中方法及功能和ArrayList中的方法大致相同,只不过LinkedList中多了关于队列相关的操作方法。

3.  Vector

和ArrayList一样,底层也是数组实现,不同的是Vector的方法默认加了锁,线程是安全的。

List接口集合迭代

List集合遍历方式有四种:

 1.  for循环遍历          2.  增强for循环遍历   

        //List集合遍历方式1:for循环
        for (int i = 0; i < arrayList.size(); i++) {
            if ("a".equals(arrayList.get(i))){
                arrayList.remove("a");//允许修改集合元素
                i--;            // 要注意索引的变化与元素位置的移动
            }
            
        }
        System.out.println(arrayList);
        System.out.println("----------------");
        
        //List集合遍历方式2:增强for循环
        for (String s:arrayList) {
            System.out.println(s);   //不能修改集合元素
        }

 3.  迭代器遍历 (Iterator)

        //List集合遍历方式3:使用迭代器遍历
        //获得集合对象的迭代器对象
       Iterator<String> it = arrayList.iterator();
        while(it.hasNext()){
            String s = it.next();//获取下一个院系
            if (s.equals("a")) {
                it.remove();  //使用迭代器对象删除元素
            }
        }
        System.out.println(arrayList);

4.  ListIterator迭代器:

public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList();
        arrayList.add("a");
        arrayList.add("b");
        arrayList.add("c");
        arrayList.add("d");
        /*
         ListIterator迭代器只能对List接口下的实现遍历
         ListIterator(index)可以从指定位置开始向前向后遍历
         */
        ListIterator<String> listIterator= arrayList.listIterator(arrayList.size());
        while(listIterator.hasPrevious()){
            System.out.println(listIterator.previous());//逆序遍历
        }
    }

Set接口

Set接口也继承了Collection接口,Set中所储存的元素是不重复的,但是是无序的,Set中的元素没有索引。

Set接口的实现类

● HashSet 

1. HashSet类中的元素不能重复

 public static void main(String[] args) {
        HashSet set =new HashSet<>();
        set.add("a");
        set.add("a");
        set.add("b");
        set.add("c");    //元素是不重复的
        System.out.println(set);
    }

2. HashSet类中的元素是无序的 

public static void main(String[] args) {
        HashSet set =new HashSet<>();
        set.add("c");
        set.add("s");
        set.add("x");
        set.add("d");    //元素是无序的
        System.out.println(set);

        set.remove("s");//没有索引,只能根据内容遍历
        set.iterator();//没有索引,要用迭代器遍历

    }

HashSet在添加元素时,是如何判断元素重复的?          *  重点  * 

在底层会先调用hashCode(),注意,Object中的hashCode()返回的是对象的地址,此时并不会调用;此时调用的是类中重写的hashCode(),返回的是根据内容计算的哈希值,遍历时,会用哈希值先比较是否相等,会提高比较的效率;但哈希值会存在问题:内容不同,哈希值相同;这种情况下再调equals比较内容,这样既保证效率又确保安全。

例:

这是错误写法,此时默认调用的是Object类中hashCode( ),返回对象地址

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

public class Student {
    private String name ;
    private String num;


    public Student(String name, String num) {
        this.name = name;
        this.num = num;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", num='" + num + '\'' +
                '}';
    }
    
        public static void main(String[] args) {
            HashSet<Student> set = new HashSet<>();
            Student s1 = new Student("小王1","10001");
            Student s2 = new Student("小王2","10002");
            Student s3 = new Student("小王3","10003");
            Student s4 = new Student("小王1","10001");
            set.add(s1);
            set.add(s2);
            set.add(s3);
            set.add(s4);
            System.out.println(set);
            
        }
    }

 正确写法应该是,在Student类中重写hashCode()和equals()

package Demo;

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

public class Student {
    private String name ;
    private String num;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return num.equals(student.num);
    }

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

    public Student(String name, String num) {
        this.name = name;
        this.num = num;
    }

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

        public static void main(String[] args) {
            HashSet<Student> set = new HashSet<>();
            Student s1 = new Student("小王1","10001");
            Student s2 = new Student("小王2","10002");
            Student s3 = new Student("小王3","10003");
            Student s4 = new Student("小王1","10001");
            set.add(s1);
            set.add(s2);
            set.add(s3);
            set.add(s4);
            System.out.println(set);

        }
    }

这样就能避免重复了(此图是s1,s4重复,但只输出s1)

补充:如何快速生成hashCode()和equals()的重写方法?

右键选择Generate,选择equals()and hashCode(),选择重写的属性。

● TreeSet

......敬请期待^_^

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

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

相关文章

Rabbitmq消息丢失-生产者消息丢失(一)

说明&#xff1a;消息生产者在将数据发送到Mq的时候&#xff0c;可能由于网络等原因造成数据投递失败。 消息丢失大致分三种&#xff1a;这里说的是生产者消息丢失&#xff01; 分析原因&#xff1a; 1.有没有一种可能&#xff0c;我刚发送消息&#xff0c;消息还没有到交换…

Matlab|配电网智能软开关(sop)规划模型

目录 1 主要内容 目标函数 2 部分程序 3 程序结果 3.1 sop选址定容优化模型 3.2 对比算例&#xff08;不含sop&#xff09; 4 下载链接 1 主要内容 该程序参考文献《基于改进灵敏度分析的有源配电网智能软开关优化配置》&#xff0c;采用二阶锥算法&#xff0c;以改进的…

Vue3+element-plus复杂表单分组处理

一、为什么表单要分组处理&#xff1f; 方便表单字段的复用&#xff1a;例如&#xff0c;你的表单有十个字段会在很多的表单都会用到&#xff0c;那么表单则需要进行分组进行表单复用&#xff1b;实现不同角色的表单权限控制&#xff1a;例如一个表单有60个字段&#xff0c;角…

STM32 NAND FLASH知识点

1.NAND FLASH的简介 NAND FLASH 的概念是由东芝公司在 1989 年率先提出&#xff0c;它内部采用非线性宏单元模式&#xff0c;为固态大容量内存的实现提供了廉价有效的解决方案。 NAND FLASH 存储器具有容量较大&#xff0c;改写速度快等优点&#xff0c;适用于大量数据的存储&…

【MySQL】事务、锁

目录 事务案例场景模拟实现转账&#xff1a;从张三的账户转账500元到李四的账户SQL示例异常 什么是事务事务的特性&#xff0c;简称ACID 属性实现原理redo logundo log MySQL 中一条 SQL 更新语句的执行过程( InnoDB 存储引擎)事务的提交流程隔离性并发事务产生的问题事务隔离级…

434G数据失窃!亚信安全发布《勒索家族和勒索事件监控报告》

最新态势快速感知 最新一周全球共监测到勒索事件90起&#xff0c;与上周相比数量有所增加。 lockbit3.0仍然是影响最严重的勒索家族&#xff1b;alphv和cactus恶意家族也是两个活动频繁的恶意家族&#xff0c;需要注意防范。 Change Healthcare - Optum - UnitedHealth遭受了…

【Python】外网远程登录访问jupyter notebook+pycharm使用ipython

第一步&#xff1a;创建python虚拟环境 conda create -n py3610 python3.6.10第二步&#xff1a;安装ipython pip install ipython pip install ipython notebook第三步&#xff1a;创建 IPython Notebook 服务器配置文件 # 进入python交互shell&#xff0c;设置密码 >&…

SpringCloud(19)之Skywalking应用上篇

一、Skywalking概述 随着互联网架构的扩张&#xff0c;分布式系统变得日趋复杂&#xff0c;越来越多的组件开始走向分布式化&#xff0c;如微服务、消 息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用&#xff0c;这些组件共同构成了繁杂的分布式网络。 思考以下…

Leaflet 加载高德地图

前言 在前面的文章中&#xff0c;我们学习了如何使用 Leaflet 创建一个基本的地图。在本文中&#xff0c;我们将学习如何在 Leaflet 中加载高德地图&#xff0c;并结合实际应用构建地图点击事件。 一、介绍 高德地图是一款由高德软件提供的数字地图服务&#xff0c;在国内使用…

在国内如何申请US,visa卡?

随着跨境与AI的发展大家对美国虚拟卡的需求也越来越多&#xff0c;比如说亚马逊、ebay、Etsy、ChatGPTPLUS、midjourney、POE等等软件以及海淘的需要&#xff0c;所以我们需要用到美国虚拟卡的场景就越来越多 如何获得一张US 虚拟信用卡&#xff1f; 方法很简单&#xff0c;点…

React-子传父

1.概念 说明&#xff1a;React中子组件向父组件传递数据通常涉及回调函数和状态提升等方法。 2.代码实现 2.1绑定事件 说明&#xff1a;父组件绑定自定义事件 <Son onGetSonMsg{getMsg}></Son> 2.2接受事件 说明&#xff1a;子组件接受父组件的自定义事件名称…

【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &#x1f680; 本…

【Pytorch入门】常见Transforms/ __call__方法

在Python中&#xff0c;__call__方法是一个特殊方法&#xff0c;用于使对象可以像函数一样被调用。当一个对象实现了__call__方法时&#xff0c;可以直接使用括号运算符将对象作为函数调用。 通过实现__call__方法&#xff0c;可以为对象提供函数式的行为&#xff0c;使其更加…

超全Chat GPT论文修改指令

文献综述指令润色修改指令论文选题指令论文大指令研究理论指令论文致谢指令参考文献指令论文润色整体逻辑论文整体优化提问指令 1&#xff0e;文献综述指令 请你帮我写一份关于&#xff08;研究主题&#xff09;的文献综述。我的论文选题方向是 XXXX &#xff0c;我已经找到了…

Vue.js 修饰符:精准控制组件行为

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

IDEA中Maven无法下载jar包问题解决

在项目中经常会遇到jar包无法下载的问题&#xff0c;可以根据以下几种方法进行排查。 1. 排查网络连接 网络连接失败&#xff0c;会导致远程访问Maven仓库失败&#xff0c;所以应确保网络连接正常。 2. 排查Maven的配置 Maven配置文件&#xff08;settings.xml&#xff09;…

《数字图像处理(MATLAB版)》相关算法代码及其分析(3)

目录 1 对边界进行子采样 1.1 输入参数检查 1.2 处理重复坐标 1.3 计算边界最大范围 1.4 确定网格线数量 1.5 构建网格位置向量 1.6 计算曼哈顿距离 1.7 整理输出结果 1.8 返回结果 2 改变图像的存储类别 2.1 函数输入 2.2 数据类型转换 2.3 错误处理 2.4 返回结…

LabVIEW高温摩擦磨损测试系统

LabVIEW高温摩擦磨损测试系统 介绍了一个基于LabVIEW的高温摩擦磨损测试系统的软件开发项目。该系统实现高温条件下材料摩擦磨损特性的自动化测试&#xff0c;通过精确控制和数据采集&#xff0c;为材料性能研究提供重要数据支持。 项目背景 随着材料科学的发展&#xff0c;…

视觉Transformers中的位置嵌入 - 研究与应用指南

视觉 Transformer 中位置嵌入背后的数学和代码简介。 自从 2017 年推出《Attention is All You Need》以来&#xff0c;Transformer 已成为自然语言处理 (NLP) 领域最先进的技术。 2021 年&#xff0c;An Image is Worth 16x16 Words 成功地将 Transformer 应用于计算机视觉任务…

小迪安全31WEB 攻防-通用漏洞文件上传js 验证mimeuser.ini语言特性

#知识点&#xff1a; 1、文件上传-前端验证 2、文件上传-黑白名单 3、文件上传-user.ini 妙用 4、文件上传-PHP 语言特性 #详细点&#xff1a; 检测层面&#xff1a;前端&#xff0c;后端等 2、检测内容&#xff1a;文件头&#xff0c;完整性&#xff0c;二次渲染…