Java Set集合:HashSet和TreeSet类

Set 集合类似于一个罐子,程序可以依次把多个对象“丢进”Set 集合,而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set 集合中不能包含重复的对象,并且最多只允许包含一个 null 元素。

Set 实现了 Collection 接口,它主要有两个常用的实现类:HashSet 类和 TreeSet类。

Java HashSet

HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。

HashSet 允许有 null 值。

HashSet 是无序的,即不会记录插入的顺序。

HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。

HashSet 实现了 Set 接口。

Java Set集合:HashSet和TreeSet类_第1张图片

HashSet 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。

基本类型对应的包装类表如下:

基本类型 引用类型
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character

HashSet 类位于 java.util 包中,使用前需要引入它,语法格式如下:

import java.util.HashSet; // 引入 HashSet 类

以下实例我们创建一个 HashSet 对象 sites,用于保存字符串元素:

HashSet sites = new HashSet();

添加元素

HashSet 类提供了很多有用的方法,添加元素可以使用 add() 方法:

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");  // 重复的元素不会被添加
        System.out.println(sites);
    }
}

执行以上代码,输出结果如下:

[Google, Runoob, Zhihu, Taobao]

在上面的实例中,Runoob 被添加了两次,它在集合中也只会出现一次,因为集合中的每个元素都必须是唯一的。

判断元素是否存在

我们可以使用 contains() 方法来判断元素是否存在于集合当中:

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");  // 重复的元素不会被添加
        System.out.println(sites.contains("Taobao"));
    }
}

执行以上代码,输出结果如下:

true

删除元素

我们可以使用 remove() 方法来删除集合中的元素:

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        sites.remove("Taobao");  // 删除元素,删除成功返回 true,否则为 false
        System.out.println(sites);
    }
}

执行以上代码,输出结果如下:

[Google, Runoob, Zhihu]

删除集合中所有元素可以使用 clear 方法:

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        sites.clear();  
        System.out.println(sites);
    }
}

执行以上代码,输出结果如下:

[]

计算大小

如果要计算 HashSet 中的元素数量可以使用 size() 方法:

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        System.out.println(sites.size());  
    }
}

执行以上代码,输出结果如下:

4

迭代 HashSet

可以使用 for-each 来迭代 HashSet 中的元素。

实例

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet sites = new HashSet();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        for (String i : sites) {
            System.out.println(i);
        }
    }
}

执行以上代码,输出结果如下:

Google
Runoob
Zhihu
Taobao

TreeSet 类

TreeSet 类同时实现了 Set 接口和 SortedSet 接口。SortedSet 接口是 Set 接口的子接口,可以实现对集合进行自然排序,因此使用 TreeSet 类实现的 Set 接口默认情况下是自然排序的,这里的自然排序指的是升序排序。

TreeSet 只能对实现了 Comparable 接口的类对象进行排序,因为 Comparable 接口中有一个 compareTo(Object o) 方法用于比较两个对象的大小。例如 a.compareTo(b),如果 a 和 b 相等,则该方法返回 0;如果 a 大于 b,则该方法返回大于 0 的值;如果 a 小于 b,则该方法返回小于 0 的值。

表列举了 JDK 类库中实现 Comparable 接口的类,以及这些类对象的比较方式。

比较方式
包装类(BigDecimal、Biglnteger、 Byte、Double、
Float、Integer、Long 及 Short)
按数字大小比较
Character 按字符的 Unicode 值的数字大小比较
String 按字符串中字符的 Unicode 值的数字大小比较

TreeSet 类除了实现 Collection 接口的所有方法之外,还提供了如表所示的方法。

方法名称 说明
E first() 返回此集合中的第一个元素。其中,E 表示集合中元素的数据类型
E last() 返回此集合中的最后一个元素
E poolFirst() 获取并移除此集合中的第一个元素
E poolLast() 获取并移除此集合中的最后一个元素
SortedSet subSet(E fromElement,E toElement) 返回一个新的集合,新集合包含原集合中 fromElement 对象与 toElement
对象之间的所有对象。包含 fromElement 对象,不包含 toElement 对象
SortedSet headSet 返回一个新的集合,新集合包含原集合中 toElement 对象之前的所有对象。
不包含 toElement 对象
SortedSet tailSet(E fromElement) 返回一个新的集合,新集合包含原集合中 fromElement 对象之后的所有对
象。包含 fromElement 对象

注意:表面上看起来这些方法很多,其实很简单。因为 TreeSet 中的元素是有序的,所以增加了访问第一个、前一个、后一个、最后一个元素的方法,并提供了 3 个从 TreeSet 中截取子 TreeSet 的方法。

例 2:本次有 5 名学生参加考试,当老师录入每名学生的成绩后,程序将按照从低到高的排列顺序显示学生成绩。此外,老师可以查询本次考试是否有满分的学生存在,不及格的成绩有哪些,90 分以上成绩的学生有几名。

下面使用 TreeSet 类来创建 Set 集合,完成学生成绩查询功能。具体的代码如下:

public class Test08 {
    public static void main(String[] args) {
        TreeSet scores = new TreeSet(); // 创建 TreeSet 集合
        Scanner input = new Scanner(System.in);
        System.out.println("------------学生成绩管理系统-------------");
        for (int i = 0; i < 5; i++) {
            System.out.println("第" + (i + 1) + "个学生成绩:");
            double score = input.nextDouble();
            // 将学生成绩转换为Double类型,添加到TreeSet集合中
            scores.add(Double.valueOf(score));
        }
        Iterator it = scores.iterator(); // 创建 Iterator 对象
        System.out.println("学生成绩从低到高的排序为:");
        while (it.hasNext()) {
            System.out.print(it.next() + "\t");
        }
        System.out.println("\n请输入要查询的成绩:");
        double searchScore = input.nextDouble();
        if (scores.contains(searchScore)) {
            System.out.println("成绩为: " + searchScore + " 的学生存在!");
        } else {
            System.out.println("成绩为: " + searchScore + " 的学生不存在!");
        }
        // 查询不及格的学生成绩
        SortedSet score1 = scores.headSet(60.0);
        System.out.println("\n不及格的成绩有:");
        for (int i = 0; i < score1.toArray().length; i++) {
            System.out.print(score1.toArray()[i] + "\t");
        }
        // 查询90分以上的学生成绩
        SortedSet score2 = scores.tailSet(90.0);
        System.out.println("\n90 分以上的成绩有:");
        for (int i = 0; i < score2.toArray().length; i++) {
            System.out.print(score2.toArray()[i] + "\t");
        }
    }
}

如上述代码,首先创建一个 TreeSet 集合对象 scores,并向该集合中添加 5 个 Double 对象。接着使用 while 循环遍历 scores 集合对象,输出该对象中的元素,然后调用 TreeSet 类中的 contains() 方法获取该集合中是否存在指定的元素。最后分别调用 TreeSet 类中的 headSet() 方法和 tailSet() 方法获取不及格的成绩和 90 分以上的成绩。

运行该程序,执行结果如下所示。

------------学生成绩管理系统-------------
第1个学生成绩:
53
第2个学生成绩:
48
第3个学生成绩:
85
第4个学生成绩:
98
第5个学生成绩:
68
学生成绩从低到高的排序为:
48.0    53.0    68.0    85.0    98.0   
请输入要查询的成绩:
90
成绩为: 90.0 的学生不存在!

不及格的成绩有:
48.0    53.0   
90 分以上的成绩有:
98.0   

注意:在使用自然排序时只能向 TreeSet 集合中添加相同数据类型的对象,否则会抛出 ClassCastException 异常。如果向 TreeSet 集合中添加了一个 Double 类型的对象,则后面只能添加 Double 对象,不能再添加其他类型的对象,例如 String 对象等。

你可能感兴趣的:(集合,java,python,开发语言)