一般來說,如果被別人問到一個問題:誰和誰的區別,在回答問題的時候,第一步應該回答的是他們之間有什么相似之處,充分變現出對技術的理解。
相同點:List
和Set
都是Collection
集合的子級接口!所以都具有Collection
這個借口所定義的所有的方法,比如添加和移除元素。
不同點:List
是序列的,主要表現為其中的各元素在內存中是存在順序規則的;另外,List
中的元素是可以重復的,即可以向同一個List
集合中反復添加相同的數據;
Set
是散列的,主要表現為其中的各元素在內存中的位置是散列的,如果使用不同的實現類來存儲數據,最終在顯示Set
集合中的所有元素時,顯示結果可能是無序的(HashSet
),或根據排序規則進行排列的(TreeSet
),或根據添加順序進行排列的(LinkedHashSet
);(注意並不是說整個集合是,而是最后的顯示結果,看到的結果是這樣的)。所以不能直接說Set是無序的。
另外,Set
中的元素是不可重復的,即不可以向同一個Set
集合中反復添加相同的數據,關於“是否相同”,取決於equals()
的對比結果與hashCode()
值的對比,如果2個對象的equals()
對比為true
,並且hashCode()
值相等,則視為“相同”!
所以,是否相同,取決於hashCode和equals方法,是先比較的hashCode再比較equals,如果hashCode相同,再比較equals,如果hashCode不同,就不比較了。
一、注意:不要用有序和無序來描述List集合和Set集合。
比如Set集合,要看用的是哪個實現類:
(1)使用HashSet作為實現類,結果是無序的;
(2)使用TreeSet作為實現類,結果為12345有序的;
(3)使用LinkedHashSet實現類,結果與添加順序一致;
所以,直接說Set是無序的,這種說法是不精准的。
詳細如下:
1.使用HashSet作為實現類,輸出為:[str-4, str-5, str-2, str-3, str-1],顯示結果是無序的;
package cn.tedu.spring;
import java.util.HashSet;
import java.util.Set;
public class CollectionDemo {
public static void main(String[] args) {
Set<String> strings = new HashSet<String>();
strings.add("str-1");
strings.add("str-5");
strings.add("str-3");
strings.add("str-2");
strings.add("str-4");
System.out.println(strings);
//輸出為:[str-4, str-5, str-2, str-3, str-1]
}
}
2.使用TreeSet作為實現類,輸出為[str-1, str-2, str-3, str-4, str-5],顯示結果是有序的;
package cn.tedu.spring;
import java.util.Set;
import java.util.TreeSet;
public class CollectionDemo {
public static void main(String[] args) {
Set<String> strings = new TreeSet<String>();
strings.add("str-1");
strings.add("str-5");
strings.add("str-3");
strings.add("str-2");
strings.add("str-4");
System.out.println(strings);
//輸出為:[str-1, str-2, str-3, str-4, str-5]
}
}
3.使用 LinkedHashSet作為實現類,輸出為:[str-1, str-5, str-3, str-2, str-4],和添加的順序一致,顯示結果是有序的;
package cn.tedu.spring;
import java.util.LinkedHashSet;
import java.util.Set;
public class CollectionDemo {
public static void main(String[] args) {
Set<String> strings = new LinkedHashSet<String>();
strings.add("str-1");
strings.add("str-5");
strings.add("str-3");
strings.add("str-2");
strings.add("str-4");
System.out.println(strings);
//輸出為:[str-1, str-5, str-3, str-2, str-4]
}
}
所以,直接說Set是無序的,這種說法是不精准的。
而對於Set
中的元素是不可重復的:
演示代碼:
package cn.tedu.spring;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class CollectionDemo {
public static void main(String[] args) {
Set<String> strings = new LinkedHashSet<String>();
strings.add("str-1");
strings.add("str-5");
strings.add("str-3");
strings.add("str-2");
strings.add("str-2");
strings.add("str-2");
strings.add("str-2");
strings.add("str-2");
strings.add("str-4");
System.out.println(strings);
//重點關注Set集合能不能重復,是哪個實現類不重要
Set<Student> students = new HashSet<Student>();
students.add(new Student("Mike", 18));
students.add(new Student("Frank", 20));
students.add(new Student("Frank", 20));
//這行代碼是復制上一行的
//這個相同的student,是可以加入進去的,但絕對不是因為是new出來的這個原因
students.add(new Student("Frank", 25));
students.add(new Student("Joe", 25));
//為了不一橫排輸出,寫一個遍歷好看些
for (Student student : students) {
System.out.println(student);
}
}
}
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//下面的兩個重寫方法,都是用Source來生成的,一鍵生成
//而開發工具不同,可能生成的代碼是不同的
//生成的這兩個方法,目的是為了加入的屬性值的內容相同,即使是new出來的對象,也看做同一個數據,也不能加入集合
//各個屬性,比如name和age的值相同,它的hashcode就一定相同,equals的對比結果也一定是true
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
//下面這個是自動生成的
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
如何輸出Set集合中的單個元素?
一般Set集合,就是遍歷輸出,挨個輸出里面的所有元素,
只有一種情況是輸出Set中的單個元素,就是確定這Set的實現類是LinkedHashSet,因為Linked的元素存儲結構是一個鏈一個的,所以在LinkedHashSet里面的數據其實是有下標的,或者說是有索引位置的,所以只有這種Set我們才會在當中獲取第3個元素或第5個元素。如果是一般的HashSet或TreeSet我們根本就不考慮要獲取其中的某一個。