JAVA常用集合set

一、set集合概述

Java集合框架中的Set接口是Collection接口的一个子接口,它表示一个无序且不包含重复元素的集合。Set接口的主要目的是确保集合中的元素唯一性,即集合中不允许出现重复的元素。

它继承自Collection接口,并且有两个主要的实现类:HashSetTreeSet

二、set的遍历方式

1,使用迭代器

2、用增强for循环

3、不能使用索引方法获取

演示示例:

public class SetDemo {
    public static void main(String[] args) {
        HashSet set = new HashSet();//添加元素的顺序和输出顺序无关,
        set.add("ad");
        set.add("ba");
        set.add("cv");
        set.add("ad");//无法添加重复元素
        set.add(new Student("zhangsan",12,98,"1"));
        set.add(new Student("zhangsan",12,98,"1"));
        System.out.println(set);
        System.out.println(set.size());
        //不能靠索引遍历,只能用增强for循环和Iterator迭代器
        for (Object o:set){
            System.out.println(o);
        }
        System.out.println("");
        Iterator iterator=set.iterator();//迭代器
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

三、HashSet

1,HashSet简述

HashSetSet接口最常用的实现类之一。它使用哈希表来存储元素,提供快速的添加、删除和查找操作。HashSet不保证元素的顺序,并且允许包含一个null元素。

2,主要特点

  • 无序性HashSet不保证元素的顺序,即元素的插入和迭代顺序可能不一致。
  • 性能:它通常提供更快的添加、删除和查找操作。
  • 实现:基于哈希表实现,通过元素的hashCode()方法来确定元素存储的位置。

3,代码示例

import java.util.HashSet;//导入HashSet, 用于实现Set接口

public class SetDemo3 {
    public static void main(String[] args) {
        HashSet set = new HashSet();// 创建HashSet对象
//说明
//1. 在执行add方法后,会返回一个boolean值
//2. 如果添加成功,返回 true, 否则返回false
//3. 可以通过 remove 指定删除哪个对象
        System.out.println(set.add("john"));//true
        System.out.println(set.add("lucy"));// true
        System.out.println(set.add("john"));// false
        System.out.println(set.add("jack"));// true
        System.out.println(set.add("Rose"));// true
        set.remove("john");//删除john
        System.out.println("set=" + set);//[jack, Rose, lucy], 顺序不一定
//
        set = new HashSet();//创建HashSet对象
        System.out.println("set=" + set);//[]
//4 Hashset 不能添加相同的元素/数据?
        set.add("lucy");//添加成功
        set.add("lucy");//加入不了
        set.add(new Dog("tom"));//OK
        set.add(new Dog("tom"));//Ok
        System.out.println("set=" + set);//[Dog{name='tom'}, Dog{name='tom'},

        set.add(new String("feis"));//ok

        set.add(new String("feis"));//加入不了,原因是String类重写了equals方法
        System.out.println("set=" + set);//[Dog{name='tom'}, Dog{name='tom'},
    }
}

class Dog { //定义了Dog类
    private String name;

    public Dog(String name) {
        this.name = name;
    }

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

四、Set 接口实现类-LinkedHashSet

1) LinkedHashSet 是HashSet 的子类

2)LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组+双向链表

3)LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使 得元素看起来是以插入顺序保存的。

4) LinkedHashset 不允许添重复元素

使用示例:

package Java基础.常用类.集合.set;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

public class linkhashset1 {
    public static void main(String[] args) {
        Set<Car> set=new LinkedHashSet();
        set.add(new Car("1",1));
        set.add(new Car("1",1));
        set.add(new Car("2",1));
        set.add(new Car("3",1));
        set.add(new Car("4",1));
        for (Car o:set){
            o.toString();
        }
    }
}
class Car{
    private String name;
    private int pri;

    public Car(String name, int pri) {
        this.name = name;
        this.pri = pri;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return pri == car.pri && Objects.equals(name, car.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, pri);
    }

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

五、Set 接口实现类-TreeSet

1 ,TreeSet实现原理

TreeSet使用红黑树结构对加入的元素进行排序存放,所以放入TreeSet中元素必须是可“排序”的。

2,TreeSet主要特点

  • 有序性TreeSet保证元素处于排序状态,可以按照自然顺序或通过实现Comparator接口来指定元素的排序方式。
  • 性能:对于需要有序元素集的场景,TreeSet是一个好的选择,但通常比HashSet慢,因为它基于红黑树实现。
  • 实现:基于平衡二叉搜索树(通常是红黑树)实现。

3,可排序的对象

TreeSet可是采用两种方法实现排序:自然排序和定制排序。默认情况,TreeSet采用自然排序。

TreeSet调用调用集合元素的CompareTo()方法,根据该方法的返回值来比较元素之间的大小, 然后进行“升序”排列,这种排序方式我们称之为自然排列。

注意:如果想采用自然排序,则要存储的对象所属类必须实现Comparable 接口。该接口只有 一个方法public int compareTo(Object obj),必须实现该方法。

compareTo方法的实现规则:

返回 0,表示 this == obj。//则不会添加新对象(this)

返回正数,表示 this> obj //添加到原来对象(obj)的右边

返回负数,表示 this < obj // 添加到原来对的左边

4,演示代码

package Java基础.常用类.集合.set;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Done5 {
    public static void main(String[] args) {
        TreeSet<StudentScore> set = new TreeSet();
        set.add(new StudentScore("张三", 90, 85, 75));
        set.add(new StudentScore("张三", 90, 85, 75));
        set.add(new StudentScore("李四", 79, 88, 90));
        set.add(new StudentScore("老六", 90, 65, 90));
        set.add(new StudentScore("王五", 87, 65, 66));
        for (StudentScore student : set) {
            System.out.println(student.toString());
        }
    }
}

class StudentScore implements Comparable<StudentScore> {
    private String name;
    private double chinese, math, english;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public double getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public double getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    public StudentScore(String name, double chinese, double math, double english) {
        this.name = name;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    @Override
    public String toString() {
        return "Student{" +
                "姓名='" + name + '\'' +
                ", 语文成绩=" + chinese +
                ", 数学成绩=" + math +
                ", 英语成绩=" + english +
                ", 总成绩=" + (chinese + english + math) +
                '}';
    }

    public double Score() {
        return this.chinese + this.english + this.math;
    }

    @Override
    public int compareTo(StudentScore o) {
        int rs = (int) (o.Score() - this.Score());
        if (rs == 0) {
            if (o.name.equals(this.name)) {
                return 0;
            } else {
                return -1;
            }
        }
        return rs;
    }
}

按成绩从大到小排序

5,定制排序

使用Comparable接口定义排序顺序有局限性:实现此接口的类只能按compareTo()定义的这一种方 式排序。

如果需要更加灵活地排序,我们可以自定义(Comparator)比较器,在创建TreeSet集合对象时把 我们自定义的比较器传入,则可以TreeSet会按照我们的比较器中定义的规则进行排序。

自定义比较器类,需要实现Comparator接口。

Comparator接口只有一个抽象方法需要实现: public int compare(Object a, Object b);

判断规则: 返回 0,表示a == b

返回正数,表示b > b

返回负数,表示a < b

学生类代码同上

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Student stu1 = (Student) o1;
                Student stu2 = (Student) o2;
//按照年龄的降序排序
                return stu2.getAge() - stu1.getAge();
            }
        });
        treeSet.add(new Student("张三", 21));
        treeSet.add(new Student("李四", 18));
        treeSet.add(new Student("王五", 20));
        treeSet.add(new Student("李琦", 19));
        System.out.println(treeSet);
    }
}

小结

  1. HashSet

    • 特点:HashSet 使用哈希表来存储元素,因此它提供了快速的添加、删除和查找操作。
    • 顺序:不保证元素的顺序,元素的位置取决于它们的哈希码。
    • 性能:在所有 Set 实现中,HashSet 通常提供最快的性能,尤其是在添加和查询元素时。
    • 唯一性:不允许包含重复元素,如果尝试添加重复元素,add 方法将返回 false。
    • 空值:可以包含一个 null 元素。
    • 迭代:迭代顺序是不可预测的,可能会因为哈希碰撞而变化。
  2. LinkedHashSet

    • 特点:LinkedHashSet 继承自 HashSet,它使用哈希表和双向链表来存储元素。
    • 顺序:维护了元素的插入顺序,即按照元素添加到集合的顺序来迭代。
    • 性能:由于需要维护链表,所以比 HashSet 稍慢,但仍然提供了快速的添加、删除和查找操作。
    • 唯一性:不允许包含重复元素。
    • 空值:可以包含一个 null 元素。
    • 迭代:迭代顺序是确定的,与元素添加的顺序一致。
  3. TreeSet

    • 特点:TreeSet 实现了 SortedSet 接口,使用红黑树(一种自平衡二叉搜索树)来存储元素,因此它支持高效的顺序访问和排序操作。
    • 顺序:元素按照自然顺序或者自定义比较器排序,确保元素处于排序状态。
    • 性能:在添加、删除和查找操作上比 HashSet 和 LinkedHashSet 慢,因为它需要维护元素的顺序。
    • 唯一性:不允许包含重复元素。
    • 空值:不支持包含 null 元素,因为 null 无法进行排序。
    • 迭代:迭代时按照元素的排序顺序进行。

总结:

  • 如果不需要关心元素的顺序,且对性能有较高要求,应该使用 HashSet。
  • 如果需要维护元素的插入顺序,并且愿意为此付出一定的性能代价,应该使用 LinkedHashSet。
  • 如果需要元素按照一定的顺序排列,应该使用 TreeSet,并且可以提供自定义的比较器来定义排序规则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值