List接口和Set接口都繼承自Collection接口,差別如下:
- List中的元素有序,且可以重複,元素可以用下标操作
- Set中的元素無序,且不能重複,元素無法用下标操作
下面我們僅僅介紹Set接口的使用,List接口的使用請參考:
http://blog.csdn.net/u011983531/article/details/49735115
一、Set接口的常見操作
因為我們經常使用Set接口來操作它的實作類(如:HashSet)的對象,是以對Set接口中常見的操作,一定要非常熟悉。
注:Set中的元素無法用下标操作
(1)添加
//如果set 中尚未存在指定的元素,則添加此元素
boolean add(E e)
//如果set 中沒有指定collection 中的所有元素,則将其添加到此set 中
boolean addAll(Collection<? extends E> c)
(2)删除
//移除此 set 中的所有元素
void clear()
//如果 set 中存在指定的元素,則将其移除
boolean remove(Object o)
//移除 set 中那些包含在指定 collection 中的元素
boolean removeAll(Collection<?> c)
(3)查找
//傳回在此 set 中的元素上進行疊代的疊代器
Iterator<E> iterator()
(4)其他操作
//傳回set中的元素數
int size()
//判斷set是否為空,如果set不包含元素,則傳回 true
boolean isEmpty()
//判斷集合中是否包含指定的元素
boolean contains(Object o)
//如果此 set 包含指定 collection 的所有元素,則傳回 true
boolean containsAll(Collection<?> c)
//傳回一個包含set中所有元素的數組
Object[] toArray()
注意:由于Set中的元素是不重複的,是以在添加元素時,需要判斷Set中是否有該元素。下面的HashSet的TreeSet詳細介紹了如何保證Set中的元素不重複。
二、Set接口常見子類
HashSet:内部資料結構是哈希表,是線程不安全的。
TreeSet:内部資料結構是二叉排序樹,是線程不安全的。
1、HashSet
HashSet的内部資料結構是哈希表,下面是哈希表确定元素是否相同的方法:
首先判斷的是兩個對象的哈希值是否相同,如果相同,再判斷兩個對象的内容是否相同。
注:判斷哈希值是否相同,其實是判斷對象的hashCode()方法的傳回結果是否相同;判斷内容是否相同,用的是對象的equals()方法。如果哈希值不相同,不需要判斷equals()方法。
是以,在使用HashSet存儲對象時,必須實作對象的hashCode()方法和equals()方法。
舉例說明:
package com.ghs.test;
import java.util.HashSet;
import java.util.Set;
public class TestHashSet {
public static void main(String[] args) {
Set<Person> persons = new HashSet<Person>();
persons.add(new Person("zhangsan", ));
persons.add(new Person("lisi", ));
persons.add(new Person("zhangsan", ));
persons.add(new Person("wangwu", ));
System.out.println(persons.size());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//當name和age都相同時,表示是同一個人
@Override
public int hashCode() {
return this.name.hashCode() + age*;
}
@Override
public boolean equals(Object obj) {
if( this ==obj)
return true ;
if(!(obj instanceof Person) )
throw new ClassCastException();
Person person = (Person) obj;
return this.name.equals(person.getName()) && this.age==person.getAge();
}
}
如果Person類沒有重寫hashCode()和equals()方法,或者隻重寫了其中一個,[zhangsan,21]這條記錄都會被添加兩次。
2、TreeSet
TreeSet判斷元素是否相同的方法:
根據比較方法的傳回結果來判斷,如果是0,就是相同元素,不存儲,否則就是不同元素。
是以,在使用TreeSet存儲對象時,要麼對象實作Comparable接口,要麼定義在建立TreeSet時,傳入比較器。
(1)實作Comparable舉例:
package com.ghs.test;
import java.util.Set;
import java.util.TreeSet;
public class TestTreeSet {
public static void main(String[] args) {
Set<Person> persons = new TreeSet<Person>();
persons.add(new Person("zhangsan", ));
persons.add(new Person("lisi", ));
persons.add(new Person("zhangsan", ));
persons.add(new Person("wangwu", ));
System.out.println(persons.size());
}
}
class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 比較的主要條件:姓名
* 次要條件:年齡
*/
@Override
public int compareTo(Object obj) {
if(!(obj instanceof Person) )
throw new ClassCastException();
Person person = (Person) obj;
int temp = this.name.compareTo(person.getName());
return temp == ? this.age-person.getAge() :temp ;
}
}
如果Person類沒有實作Comparable接口,運作過程中就會出現類型轉換異常。
(2)使用比較器舉例
package com.ghs.test;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class TestTreeSet2 {
public static void main(String[] args) {
Set<Person> persons = new TreeSet<Person>(new PersonComparator());
persons.add(new Person2("zhangsan", ));
persons.add(new Person2("lisi", ));
persons.add(new Person2("zhangsan", ));
persons.add(new Person2("wangwu", ));
System.out.println(persons.size());
}
}
class Person{
private String name;
private int age;
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class PersonComparator implements Comparator{
@Override
public int compare(Object obj1, Object obj2) {
if(!(obj1 instanceof Person) )
throw new ClassCastException();
if(!(obj2 instanceof Person) )
throw new ClassCastException();
Person person1 = (Person) obj1;
Person person2 = (Person) obj2;
int temp = person1.getName().compareTo( person2.getName()) ;
return temp == ? person1.getAge()-person2.getAge():temp ;
}
}
三、周遊Set中的元素
周遊Set中的元素有兩種方法,一種是使用疊代器,另一種是直接使用增強for循環,但是不能用下标操作。
//周遊
public static void testSet(){
HashSet<Person> persons = new HashSet<Person>();
persons.add(new Person("zhangsan", ));
persons.add(new Person("lisi", ));
persons.add(new Person("wangwu", ));
//方法一:疊代器
Iterator<Person> it = persons.iterator();
for(Person p = it.next() ; it.hasNext();){
System.out.println(p.getName() +"----"+p.getAge());
}
//或者
while(it.hasNext()){
Person p = (Person) it.next() ;
System.out.println(p.getName() +"----"+p.getAge());
}
//方法二:for循環
for(Person p : persons){
System.out.println(p.getName() +"----"+p.getAge());
}
}