Java集合详解(List和Set)

简介: Java集合讲解!入门学习!

一. 集合的诞生

集合是为了弥补数组的不足而存在。

集合相对于数组优势在于:a.集合的长度可以动态改变;b.集合中能够存放多种类型的数据。

在这里插入图片描述

二. 集合的家族

Collection接口是所有单值集合的父接口

List接口与Set接口的区别:

在这里插入图片描述

一个集合类的对象就一个集合。

Collection中常用的方法

方法名 描述
add(E e) 确保此 collection 包含指定的元素(可选操作)。
clear() 移除此 collection 中的所有元素(可选操作)。
contains(Object o) 如果此 collection 包含指定的元素,则返回true
equals(Object o) 比较此 collection 与指定对象是否相等
isEmpty() 如果此 collection 不包含元素,则返回true。
iterator() 返回在此 collection 的元素上进行迭代的迭代器。
remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话。
size() 返回此 collection 中的元素数。
toArray() 返回包含此 collection 中所有元素的数组。

1、List集合有序,可重复)

ArrayList:LinkedList:

①ArrayList: 底层数据结构是数组,查询快,增删慢

②LinkedList: 底层数据结构是链表,查询慢,增删快

两者共同缺点: 线程不安全,效率高


Vector:

①优点: 底层数据结构是数组,查询快,增删慢。

②缺点: 线程安全,效率低

小结:底层数据结构特点决定其性能特性

---

2、Set集合—(无序,唯一)

  • Set接口是Collection的子接口,表示元素无序且不可重复的集合。

在这里插入图片描述
(1)HashSet:

底层数据结构是哈希表。(无序,唯一)

如何来保证元素唯一性?

1、依赖两个方法:hashCode()和equals()
2、HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。


具体实现唯一性的比较过程:

1.存储元素时首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,肯定是不同的对象。
2.hashCode值相同,再比较equals方法。
3.equals相同,对象相同。(则无需储存)


(2)LinkedHashSet:

底层数据结构是链表和哈希表 (FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。


(3)TreeSet:

底层数据结构是红黑树。(唯一,有序)

如何保证元素排序的呢?

1、自然排序

2、比较器排序


如何保证元素唯一性的呢?

1、根据比较的返回值是否是0来决定

2、TreeSet底层数据结构采用红黑树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造)

3、自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;

4、比较器排序要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;


TreeSet实践案例

①在元素类中定义排序规则

import java.util.TreeSet;

//创建学生类实践
public class Student implements Comparable<Student> {
    private String stuNum;
    private String stuName;
    private String stuSex;
    private int stuAge;

    public Student(String stuNum, String stuName, String stuSex, int stuAge) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.stuSex = stuSex;
        this.stuAge = stuAge;
    }

    public String getStuNum() {
        return stuNum;
    }

    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public String getStuSex() {
        return stuSex;
    }

    public void setStuSex(String stuSex) {
        this.stuSex = stuSex;
    }

    public int getStuAge() {
        return stuAge;
    }

    public void setStuAge(int stuAge) {
        this.stuAge = stuAge;
    }

    @Override
    public String toString() {
        return "Student{" +
                "编号'" + stuNum + '\'' +
                ", 姓名='" + stuName + '\'' +
                ", 性别='" + stuSex + '\'' +
                ", 年龄=" + stuAge +
                '}';
    }

        //重写里面的compareTo()方法
    @Override
    public int compareTo(Student o) {
        // compareTo 的参数o表示集合中已经存在的元素
        return this.stuAge - o.stuAge;
    }

    //案例
    public static void main(String[] args) {
        //TreeSet<Student> ts = new TreeSet<Student>();

        TreeSet<Student> ts =new TreeSet<Student>();
        Student s1 = new Student("10001", "Lilei", "M", 20);
        Student s2 = new Student("10002", "HanMeimei", "F", 19);
        Student s3 = new Student("10003", "Lily", "F", 21);
        Student s4 = new Student("10004", "Tom", "M", 22);
        ts.add(s1);    // [s1]
        ts.add(s2); // [s2,s1]
        ts.add(s3); // [s2,s1,s3]
        ts.add(s4); // [s2,s1,s3,s4]
        System.out.println(ts);
    }
}

  • 比较器中我们按年龄排序,输出结果也是按年龄排序
[Student{编号'10002', 姓名='HanMeimei', 性别='F', 年龄=19}, 
Student{编号'10001', 姓名='Lilei', 性别='M', 年龄=20},
 Student{编号'10003', 姓名='Lily', 性别='F', 年龄=21},
  Student{编号'10004', 姓名='Tom', 性别='M', 年龄=22}]

给TreeSet集合指定比较器(未继承接口)

import java.util.Comparator;
import java.util.TreeSet;

public class Student {
    private String stuNum;
    private String stuName;
    private String stuSex;
    private int stuAge;

    public Student(String stuNum, String stuName, String stuSex, int stuAge) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.stuSex = stuSex;
        this.stuAge = stuAge;
    }

    public String getStuNum() {
        return stuNum;
    }

    public void setStuNum(String stuNum) {
        this.stuNum = stuNum;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public String getStuSex() {
        return stuSex;
    }

    public void setStuSex(String stuSex) {
        this.stuSex = stuSex;
    }

    public int getStuAge() {
        return stuAge;
    }

    public void setStuAge(int stuAge) {
        this.stuAge = stuAge;
    }

    @Override
    public String toString() {
        return "Student{" +
                "编号'" + stuNum + '\'' +
                ", 姓名='" + stuName + '\'' +
                ", 性别='" + stuSex + '\'' +
                ", 年龄=" + stuAge +
                '}';
    }

    //案例
    public static void main(String[] args) {

        //切记这里是Comparator
        Comparator<Student> cptr = new Comparator<Student>() {
            //o1表示向集合中新增的元素,o2表示集合中已经存在的元素
            public int compare(Student o1, Student o2) {
                int i = o1.getStuAge() - o2.getStuAge();
                return i;
            }
        };
        
        TreeSet<Student> ts = new TreeSet<Student>(cptr);
        Student s1 = new Student("10001", "Lilei", "M", 20);
        Student s2 = new Student("10002", "HanMeimei", "F", 19);
        Student s3 = new Student("10003", "Lily", "F", 21);
        Student s4 = new Student("10004", "Tom", "M", 22);
        ts.add(s1);    // [s1]
        ts.add(s2); // [s2,s1]
        ts.add(s3); // [s2,s1,s3]
        ts.add(s4); // [s2,s1,s3,s4]
        System.out.println(ts);
    }
}

  • 输出结果
[Student{编号'10002', 姓名='HanMeimei', 性别='F', 年龄=19}, 
Student{编号'10001', 姓名='Lilei', 性别='M', 年龄=20},
 Student{编号'10003', 姓名='Lily', 性别='F', 年龄=21},
  Student{编号'10004', 姓名='Tom', 性别='M', 年龄=22}]

注意:小编我在编辑过程将上例中Comparator打错成Comparable导致自定义程序无法出结果,希望大家用比较器也多注意。


补充:Comparable和Comparator区别

  • 对于Comparable接口来说,被比较对象所属的类需要直接实现Comparable接口,实现该接口的类被赋予一个自然顺序,而且该自然顺序只有一个,而Comparator是一个比较器接口,被比较对象所属的类不需要直接实现该接口,可以单独写一个比较器类实现该接口,作为比较对象的一个比较器,对于一个类来说,可以实现多个比较器。
  • Comparator可以选择对null进行比较,而Comparable不可以。主要是因为Comparator的比较对象都是compare方法的参数,而Comparable的比较方法compareTo方法需要对象来调用,而对象为null时(null.compareTo(obj)),会出现异常。

Lambda表达式

是JDK1.8新增的表达式语法,实际上就是一个语法糖,用于对接口中的方法进行实现。

代码修改对比

        //切记这里是Comparator
        Comparator<Student> cptr = new Comparator<Student>() {
            //o1表示向集合中新增的元素,o2表示集合中已经存在的元素
            public int compare(Student o1, Student o2) {
                int i = o1.getStuAge() - o2.getStuAge();
                return i;
            }
        };
        TreeSet<Student> ts = new TreeSet<Student>(cptr);

Lambda表达式的应用

 //Lambda表达式
        TreeSet<Student> ts2 = new TreeSet<Student>((o1,o2)->o1.getStuAge()-o2.getStuAge());

输出结果一样,但是格式更加简洁


May you find the work you are willing to devote to and love it.

非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!

愿你们奔赴在自己的热爱里!

目录
相关文章
|
5天前
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
|
5天前
|
Java 程序员 C语言
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
面试官:那TreeSet要怎么定制排序?TreeSet的自定义排序我们要利用Comparator接口,通过向TreeSet传入自定义排序规则的Comparator来实现。官方源码是这么解释的,南友们看一看。// 构造一个新的空树集,根据指定的比较器进行排序。// 插入到集合中的所有元素都必须能够通过指定的比较器相互比较: comparator. compare(e1, e2)不得对集合中的任何元素e1和e2抛出ClassCastException。
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
|
6天前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
1天前
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。
|
4天前
|
Java 数据库
成功解决:java.sql.SQLSyntaxErrorException: Unknown column ‘origin_name‘ in ‘field list‘
这篇文章分享了作者在使用SpringBoot和Mybatis-plus时遇到的SQLSyntaxErrorException错误,原因是字段映射不正确,并通过修改数据库字段名称或关闭自动驼峰命名转换配置来成功解决了这个问题。
成功解决:java.sql.SQLSyntaxErrorException: Unknown column ‘origin_name‘ in ‘field list‘
|
2月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
183 1
|
21天前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
25天前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
1月前
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
|
2月前
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
30 3