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

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

目录
相关文章
|
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'.
152 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
2月前
set集合
HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素。 LinkedHashSet: LinkedHashSet 是 HashSet 的子类,并且其内部是通过 LinkedHashMap 来实现的。 TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树)。
|
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月前
|
存储 Java 开发者
Java Set:无序之美,不重复之魅!
在Java的集合框架中,Set接口以其“无序之美”和“不重复之魅”受到开发者青睐。Set不包含重复元素,不保证元素顺序,通过元素的hashCode()和equals()方法实现唯一性。示例代码展示了如何使用HashSet添加和遍历元素,体现了Set的高效性和简洁性。
48 4
|
2月前
|
存储 算法 Java
为什么Java Set如此“挑剔”,连重复元素都容不下?
在Java的集合框架中,Set是一个独特的接口,它严格要求元素不重复,适用于需要唯一性约束的场景。Set通过内部数据结构(如哈希表或红黑树)和算法(如哈希值和equals()方法)实现这一特性,自动过滤重复元素,简化处理逻辑。示例代码展示了Set如何自动忽略重复元素。
36 1
|
2月前
|
存储 算法 Java
Java中的Set,你真的了解它的“无重复”奥秘吗?
在Java的广阔天地里,Set以其独特的“无重复”特性,在众多数据结构中脱颖而出。本文将揭秘Set的“无重复”奥秘,带你领略其魅力。Set通过哈希算法和equals()方法协同工作,确保元素不重复。通过一个简单的案例,我们将展示HashSet如何实现这一特性。
45 1
|
2月前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
2月前
|
NoSQL Java Redis
List集合按照由小到大排序或者由大到小排序
List集合按照由小到大排序或者由大到小排序
51 0
下一篇
开通oss服务