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!!!

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

目录
相关文章
|
10天前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
33 3
|
28天前
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
60 20
|
27天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
44 5
|
2月前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
153 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
2月前
|
存储 缓存 安全
Java 集合框架优化:从基础到高级应用
《Java集合框架优化:从基础到高级应用》深入解析Java集合框架的核心原理与优化技巧,涵盖列表、集合、映射等常用数据结构,结合实际案例,指导开发者高效使用和优化Java集合。
47 4
|
2月前
|
存储 算法 Java
Java Set深度解析:为何它能成为“无重复”的代名词?
Java的集合框架中,Set接口以其“无重复”特性著称。本文解析了Set的实现原理,包括HashSet和TreeSet的不同数据结构和算法,以及如何通过示例代码实现最佳实践。选择合适的Set实现类和正确实现自定义对象的hashCode()和equals()方法是关键。
38 4
|
2月前
|
Java
那些与Java Set擦肩而过的重复元素,都经历了什么?
在Java的世界里,Set如同一位浪漫而坚定的恋人,只对独一无二的元素情有独钟。重复元素虽屡遭拒绝,但通过反思和成长,最终变得独特,赢得了Set的认可。示例代码展示了这一过程,揭示了成长与独特性的浪漫故事。
24 4
|
2月前
|
Java 开发者
Java Set:当“重复”遇见它,秒变“独宠”!
在Java编程中,Set接口确保集合中的元素不重复,每个元素都是独一无二的“独宠”。本文介绍了Set的两种常见实现:HashSet和TreeSet。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet基于红黑树实现,不仅去重还能对元素进行排序。通过示例代码,展示了这两种集合的具体应用,帮助开发者更好地理解和使用Set。
32 4
|
2月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
52 0
|
5月前
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。
下一篇
开通oss服务