Java中的TreeSet addAll()方法

Java中的TreeSet addAll()方法

TreeSet 类是 Set 接口的实现类之一,它是一个有序集合,可以根据元素的自然顺序或者根据构造函数所提供的 Comparator 进行排序。TreeSet中的元素不重复,和HashSet一样,对于重复元素只会保留一份。在 TreeSet 中还有一个 addAll(Collection<? extends E> c) 方法,它允许将指定集合中的所有元素添加到此TreeSet中。 然而,在使用 addAll() 方法的时候,用户需要特别留意元素的类型,否则会引发运行时异常。

addAll() 方法的用法

addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此TreeSet中。它返回一个布尔值代表是否添加了指定的集合。例如:

        Set<String> set1 = new HashSet<String>();
        set1.add("one");
        set1.add("two");
        set1.add("three");

        TreeSet<String> set2 = new TreeSet<String>();
        set2.add("four");
        set2.add("five");
        set2.add("six");

        boolean res1 = set2.addAll(set1); // 将集合set1中的元素添加到set2中
        System.out.println(res1); // true

        boolean res2 = set2.addAll(set1); // 再次添加,返回false
        System.out.println(res2); // false

        System.out.println(set2); // 会输出 [four, one, six, three, two, five]

在这个示例中,我们首先新建一个 HashSet,并向其中添加了三个字符串元素。接着,我们又新建了一个 TreeSet,并向其中添加了三个字符串元素。接着,我们使用 set2.addAll(set1) 的方式将 set1 中的元素添加到 set2 中。该方法返回一个布尔值,代表操作是否成功。由于 set2 当前是空的,因此所有元素都会成功添加到 set2 中。同样的操作过程,我们再次将 set1 中的元素添加到 set2 中。由于 set2 中已经有了这些元素,所以这次操作将会失败,并且返回 false。最后,我们打印出 set2 的元素集合,可以看到元素已经按照自然顺序进行了排序。

但值得注意的是,若 addAll(Collection<? extends E> c) 中的集合类型与TreeSet中不同,那么在添加元素时会引发Java的类型转换异常。 那么怎么解决这个问题呢?下面我们将探讨不同情况下该如何使用 addAll() 方法。

两个集合元素的类型一致

如果要将一个与 TreeSet 具有相同类型的 Collection 添加到 TreeSet 中,则应该在 addAll 方法中向将 Collections 实例传递给三个运算符 <>。例如:

        Set<Integer> set1 = new HashSet<>();
        set1.add(1);
        set1.add(2);
        set1.add(3);

        TreeSet<Integer> set2 = new TreeSet<>();
        set2.add(4);
        set2.add(5);
        set2.add(6);

        boolean res1 = set2.addAll(set1); 
        System.out.println(res1); // true

        boolean res2 = set2.addAll(set1); 
        System.out.println(res2); // false

        System.out.println(set2); // 会输出 [1, 2, 3, 4, 5, 6]

这里的 set2 是一个TreeSet<Integer>,而 set1 中也只包含了整型数字。因此,我们在调用 addAll() 方法时不需要进行类型转换即可将整型数字元素添加到 set2 中。

两个集合元素的类型不一致

如果要将一个与 TreeSet 具有不同类型的 Collection 添加到 TreeSet 中,则需要进行类型转换。例如:

        Set<Object> set1 = new HashSet<>();
        set1.add(1);
        set1.add(2);
        set1.add(3);

        TreeSet<Integer> set2 = new TreeSet<>();
        set2.add(4);
        set2.add(5);
        set2.add(6);

        boolean res1 = set2.addAll((Collection<? extends Integer>) set1); 
        System.out.println(res1); // true

        boolean res2 = set2.addAll((Collection<? extends Integer>) set1);
        System.out.println(res2); // false

        System.out.println(set2); // 会输出 [1, 2, 3, 4, 5, 6]

这里,set1 是一个 HashSet<Object>,虽然它包含了整型数字元素,但由于集合类型与 set2 不同,因此在调用 addAll() 方法时需要进行类型转换。我们使用 (Collection<? extends Integer>) set1 这种方式将 set1 转换为 Collection<? extends Integer>,这样整型数字元素就可以成功添加到 set2 中了。

addAll() 方法的源代码

最后,我们来看一下 addAll() 方法在 TreeSet 中的源代码实现。

public boolean addAll(Collection<? extends E> c) {
    Objects.requireNonNull(c);
    boolean modified = false;
    if (c instanceof SortedSet<?>) {
        SortedSet<? extends E> s = (SortedSet<? extends E>)c;
        Comparator<? super E> cc = (Comparator<? super E>)tree.comparator();
        Comparator<? super E> sc = s.comparator();
        if (cc==null && sc==null)
            modified = addAll((SortedSet<E>)s);
        else
            modified = addAllUsingComparator(s, cc);
    } else if (c instanceof Collection<?>) {
        modified = standardAddAll((Collection<? extends E>)c);
    } else {
        for (E e : c)
            modified |= add(e);
    }
    return modified;
}

其中,第 3 行代码对输入参数 c 进行了判空处理。接下来,该方法会根据 c 的类型分别进行处理:

  • 如果 c 的类型是 SortedSet<? extends E>,即输入的集合类型是有序集合,并且具有和 TreeSet 相同的排序算法,则调用 TreeSet.addAll(SortedSet<E> s) 方法进行添加。这个方法实际上就是不断调用 add() 方法进行元素逐个添加的过程。
  • 如果 c 的类型是 Collection<? extends E>,即输入的集合类型是集合类,并且具有相同的元素类型,则调用 TreeSet.standardAddAll(Collection<? extends E> c) 方法进行添加。这个方法实际上也是不断调用 add() 方法进行元素逐个添加的过程。
  • 如果 c 的类型不是有序集合也不是其他类型的集合(即元素类型与 TreeSet 不同),则调用 add(E e) 方法将集合中的元素逐个添加到 TreeSet 中。

结论

TreeSet 中的 addAll() 方法是一个很方便的集合操作方法,可以将另一个集合中的元素逐个添加到当前 TreeSet 中。但需要特别注意的是,在使用 addAll() 方法的时候,用户需要特别留意元素的类型,否则会引发运行时异常。如果要将不同类型的集合添加到 TreeSet 中,则需要进行类型转换。同时,该方法的源代码也为我们提供了使用时的参考。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程