JAVA的Set集合类
Set接口也称集合接口,Set接口和Link接口同属于Collections接口的子接口。需要注意的时,Set接口中不能存储重复的数据内容。Set接口也支持泛型操作
其定义如下:
public interface Set<E> extends Collection<E>
Set接口主要有两个子类HashSet和TreeSet
1.HashSet类
HashSet类继承自AbstractSet类,并实现leSet接口。从该类的名称可以看出,该类使用基于散列(hashing)原理的哈希表来存储元素,通过生成唯一的散列码作为关键字,从而保证了元素索引的全局唯一性。HashSet中的对象是无序的。
HashSet类的定义如下:
Public class HashSet<E> extends AbstractSet<E>
implements Set<E>,Cloneable,Serializable
HashSet类的主要方法
返回值类型 | 方法及其功能描述 |
boolean | add(E e) 如果指定的元素e尚未存在,则添加到此集合中 |
void | clean() 从该集合中删除所有元素 |
boolean | contains(Object o) 如果此集合包含指定元素o,则返回true |
boolean | isEmpty() 如果此集合不包含任何元素,则返回true |
Iterator<E> | iterator() 创建此集合中的元素迭代器对象 |
boolean | remove(Object o) 如果指定的元素o存在,从该集合中删除该元素 |
int | size() 返回此集合中的元素个数 |
例题如下:
import java.util.HashSet;
import java.util.Set;public class SetHashSet {public static void main(String[] args) {Set<String> hashSet = new HashSet<String>();hashSet.add("one");hashSet.add("two");hashSet.add("three");hashSet.add("four");hashSet.add("five");hashSet.add("six");System.out.println("Set当前集合元素:");for (String s:hashSet){System.out.println(s);}hashSet.add("two");hashSet.add("seven");System.out.println("添加之后的Set集合元素:");for (String s:hashSet){System.out.println(s);}}
}
运行结果
Set当前集合元素:
six
four
one
two
three
five
添加之后的Set集合元素:
six
four
one
seven
two
three
five
在此例题中再次添加两份数据,但是只保存seven的这份数据,two并没有保存
注意的是:
如果HashSet集合中存放的是用户自定义类,则在该类中必须重写
public boolean equals (类名anObject)
public int hashCode()
这两个方法。由于Set集合不存储重复的相同元素,因此,重写equals()给出相同元素的定义,进行比较的成员变量称为关键变量;此外HashSet类是通过hash编码进行快速存储和查找的,必须重写hashCode()方法给出每个元素的关键变量的hash编码。
hashCode()方法参考算法如下:
public int hashCode() {int code=17;code = 31*code + 关键变量1的hash值;code = 31*code + 关键变量n的hash值;return code;}
在此例子中,使用的是String类元素
各种类型关键变脸的hash值
关键变量类型 | hash值 | 关键变量类型 | hash值 |
int aInt | aInt | long aLong | (int)(aLong^(aLong >>> 32)) |
short aShort | (int)aShort | float aFloat | (int)Float.floatToRawIntBits (aFloat) |
char aChar | (int)aChar | double aDouble | long tolong = Double.doubleToLongBits(aDouble) (int)(tolong^(tolong>>>32)) |
byte aByte | (int)aByte | String str | str.hashCode() |
boolean aBoolean | (int)(aBoolean?0:1) | T object | object.hashCode() |
2.TreeSet类
TreeSet类实现了Collections、NavigableSet、Set、SortedSet等多个接口,因此可以实现按顺序对象存储。存入TreeSet类对象的元素必须实现Comparable接口。
TreeSet类的定义如下:
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>,Cloneable,Serializable
TreeSet常见的方法如下:
返回值类型 | 方法及其功能描述 |
boolean | add(E e) 如果指定的元素尚未存在,则添加到此集合中 |
E | first() 返回当前集合中的第一个元素 |
E | last() 返回当前集合中的最后一个元素 |
SortedSet<E> | headSet(E toElement) 返回此集合中元素严格小于toElement的部分的视图 |
SortedSet<E> | subSet(E fromElment,E toElement) 返回此集合中,元素范围元素从fromElement(包含)到toElement(不包含)元素的视图 |
SortedSet<E> | tailSet(E fromElement) 返回此集合中,元素大于或者等于fromElement部分的视图 |
例题如下:
import java.util.Iterator;
import java.util.TreeSet;class Person implements Comparable<Person>{private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic int compareTo(Person person) {if (this.age > person.age){return 1;}else if (this.age == person.age){return 0;}return -1;}
}
public class SetTreeSet {public static void main(String[] args) {TreeSet<Person> treeSet = new TreeSet<Person>();treeSet.add(new Person("bob", 18));treeSet.add(new Person("Jon", 23));treeSet.add(new Person("sam", 20));treeSet.add(new Person("tom", 21));Iterator<Person> iterator = treeSet.iterator();Person person;while (iterator.hasNext()){person=iterator.next();System.out.println("姓名:"+person.getName()+"年龄:"+person.getAge());}}
}
运行结果:
姓名:bob年龄:18
姓名:sam年龄:20
姓名:tom年龄:21
姓名:Jon年龄:23
在以上代码中,定义一个Person类并实现Comparable接口,在compareTo接口方法定义接口方法的逻辑;由于Comparable是一个泛型接口,如果在引用时加入泛型实参,则在实现接口时,可以直接使用泛型实参作为类型定义形参
注意的是:往集合加入对象时,顺序没有按照年龄进行排序,但输出的时候,集合的对象已经自动按照年龄进行排序,这是由于在添加的时候自动调用compareTo()方法来进行排序,这是TreeSet集合的特点,它会对存储的元素进行排序。因此,作为元素存储在TreeSet集合中时,元素对象对于的类实现Comparable接口,重写该接口的compareTo()方法和应用Arrays数组工具进行对象数组排序的要求