Set 的功能方法

Set 具有与 Collection 完全一样的接口,因此没有任何额外的功能,不像前面有两个不同

的 List。实际上 Set 就是 Collection,只是行为不同。(这是继承与多态思想的典型应用:

表现不同的行为。)Set 不保存重复的元素(至于如何判断元素相同则较为复杂,稍后便会

看到)。


 

 

Set (interface)

存入 Set 的每个元素都必须是唯一的,因为 Set 不保

存重复元素。加入 Set 的元素必须定义 equals()方法

以确保对象的唯一性。Set 与 Collection 有完全一样

的接口。Set 接口不保证维护元素的次序。

HashSet*

为快速查找设计的 Set。存入 HashSet 的对象必须定

义 hashCode()。

TreeSet

保持次序的 Set,底层为树结构。使用它可以从 Set

中提取有序的序列。

LinkedHashSet

(JDK 1.4)

具有 HashSet 的查询速度,且内部使用链表维护元素

的顺序(插入的次序)。于是在使用迭代器遍历 Set

时,结果会按元素插入的次序显示。

下例并没有演示Set 能够做的所有事情,因为它的接口与 Collection 相同,所以有些在前

例中练习过了。这里演示的只是 Set 独有的行为:

 

//:c11:Set1.java



 

 

 

// Things youcan do with Sets.

import com.bruceeckel.simpletest.*;

import java.util.*;

 

public   class Set1 {

private   static Test monitor = new Test();

static     void fill(Set s) {

    s.addAll(Arrays.asList(

"one twothree four five six seven".split(" ")));

  }

public   static    void test(Set s) {

// Stripqualifiers from class name:

    System.out.println(

      s.getClass().getName().replaceAll("\\w+\\.",                          ""));

    fill(s); fill(s); fill(s);

    System.out.println(s);       // No duplicates!

// Add anotherset to this one:

    s.addAll(s);

    s.add("one");

    s.add("one");

    s.add("one");

    System.out.println(s);

// Looksomething up:

    System.out.println("s.contains(\"one\"): " +

      s.contains("one"));

  }

public   static    void main(String[] args) {

    test(new HashSet());

    test(new TreeSet());

    test(new LinkedHashSet());

    monitor.expect(new String[] {

"HashSet",

"[one,two, five, four, three, seven, six]",

"[one,two, five, four, three, seven, six]",

"s.contains(\"one\"): true",

"TreeSet",

"[five,four, one, seven, six, three, two]",

"[five,four, one, seven, six, three, two]",

"s.contains(\"one\"): true",

"LinkedHashSet",

"[one,two, three, four, five, six, seven]",

"[one,two, three, four, five, six, seven]",

"s.contains(\"one\"): true"

    });


 

 

 

  }

}   ///:~

 

例子中向Set 添加了重复的值,但是打印的结果说明,对每一个值 Set 只接受一份实例。

 

运行此程序,你会注意到,HashSet 维护的元素次序不同于 TreeSet 和 LinkedHashSet,

因为它们保存元素的方式各有不同,使得以后还能找到元素。(TreeSet 采用红黑树的数

据结构排序元素,HashSet 则采用散列函数,这是专门为快速查询设计的。LinkedHashSet

内部使用散列以加快查询速度,同时使用链表维护元素的次序,使得看起来元素是以插入

的顺序保存的。)生成自己的类时,注意 Set 需要维护元素的存储顺序,这意味着你必须

实现 Comparable 接口,并且定义 compareTo()方法。参见下例:

 

//:c11:Set2.java

// Putting yourown type in a Set.

import com.bruceeckel.simpletest.*;

import java.util.*;

 

public   class Set2 {

private   static Test monitor = new Test();

public   static Set fill(Set a, int size) {

for(int i = 0; i < size; i++)

      a.add(new MyType(i));

return a;

  }

public   static    void test(Set a) {

    fill(a, 10);

    fill(a, 10);       // Try to add duplicates

    fill(a, 10);

    a.addAll(fill(new TreeSet(), 10));

    System.out.println(a);

  }

public   static    void main(String[] args) {

    test(new HashSet());

    test(new TreeSet());

    test(new LinkedHashSet());

    monitor.expect(new String[] {

"[2 , 4 ,9 , 8 , 6 , 1 , 3 , 7 , 5 , 0 ]",

"[9 , 8 ,7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ]",

"[0 , 1 ,2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]"

    });

  }

}   ///:~

 

本章稍后会介绍如何定义 equals()和 hashCode()。使用以上两种 Set 都必须为你的类定

义 equals(),而 hashCode(),只在你的类会被 HashSet 用到的情况下才是必要的(这


 

 

 

种可能性很大,因为HashSet 通常是使用 Set 的第一选择)。无论如何,作为一种编程风

格,当你重载equals()的时候,就应该同时重载 hashCode()。本章稍后会详细介绍这个

过程。

 

注意在 compareTo()中,我并没有使用“简单而明显”的 return i-i2。虽然这是一个常

犯的编程错误,但是如果 i  与 i2  正巧是“无符号”的 int时(如果 Java 有“无符号”unsigned

这个关键字的话,其实没有),此语句也能正常工作。如果是 Java 的有符号整数 int 则无

法确保正确,因为int 不够大,不足已表现两个有符号整数 int 的差。例如 i 是很大的正整

数,而 j 是很大的负整数,i-j就会溢出并且返回负值,这就不正确了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值