java中List與Set的常用用法
java中的集合主要分為三種:Set(集)、List(列表)、Map(對映)
下圖為List、Set和Collection的聯絡,我們可以看出List和Set均繼承自Collection,值得注意的是List、Set和Collection都為介面,不能直接例項化物件。List的兩個實現類為ArrayList和LinkedList。
1.List集合的元素是有序的(取出順序和儲存順序一致),元素可以重複
(1)ArrayList:繼承了List的特點,底層資料結構是陣列,因此它的查詢速度快,但是增刪速度慢。他是執行緒不安全的,效率高。
(2)LinkedList:同樣繼承了List的特點,底層資料結構是連結串列,所以它的增刪速度快,查詢速度慢。執行緒不安全、效率高。
新建一個測試學生類,這裡只說引用型別,不討論基本型別,後面不再論述。
鑑於篇幅原因,這裡只給出ArrayList的程式碼,因為LinkedList和ArrayList一樣的。<span style="font-size:18px;">public class Student { private String name; //學生姓名 private int age; //學生姓名 //建構函式 public Student(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 //重寫 toString()方法 public String toString() { return "姓名:" + name + "\t 年齡:" + age; } } </span>
<span style="font-size:18px;">public static void main(String[] args) { //建立一個ArrayList的集合 ArrayList<Student> list = new ArrayList<Student>(); Student s1 = new Student("張三", 19); //建立學生物件 Student s2 = new Student("李四", 17); Student s3 = new Student("小明", 18); Student s4 = new Student("小紅", 22); Student s5 = new Student("李四", 17); list.add(s1); //增加成員 list.add(s2); list.add(s3); list.add(s4); list.add(s5); //有三種遍歷方式 //1.迭代器 // Iterator<Student> iterator = list.iterator(); // while (iterator.hasNext()) { // System.out.println(iterator.next()); // } //2.for迴圈遍歷 // for (int i = 0; i < list.size(); i++) { // System.out.println(list.get(i)); // } //3.增強for迴圈 for (Student student : list) { System.out.println(student); } }</span>
通過重寫Collectios的sort方法可以實現自定排序,以上面為例,按年齡從小到大排序:
<span style="font-size:18px;">//重寫sort方法,通過匿名內部類實現
Collections.sort(list,new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if((o1.getAge()-o2.getAge())>0){
return 1;
}else if((o1.getAge()-o2.getAge())<0){
return -1;
}else
return 0;
}
});</span>
還可以通過在自定義類(Student類)中實現Comparable介面,重寫compareTo()方法來實現自定義排序,按年齡從大到小排序:
<span style="font-size:18px;">@Override
public int compareTo(Student o) {
if((this.getAge()-o.getAge())>0){
return 1;
}else if((this.getAge()-o.getAge())<0){
return -1;
}else
return 0;
}</span>
1.Set集合的元素是唯一的,不可重複(有兩種遍歷方式:1.迭代器,2.增強for.程式碼參照上面)
(1)HashSet:繼承了Set的特點,元素唯一,但是無序。底層資料結構是雜湊表,通過重寫HashCode()方法和equals()方法可以保證元素的唯一性。
(2)TreeSet:繼承了Set的特點,元素唯一而且有序(使用元素的自然順序對元素進行排序,或者根據建立 set時提供的 Comparator進行排序,具體取決於使用的構造方法)。底層資料結構是二叉樹,通過Compareable介面的compareTo()方法來保證元素的唯一性。
<span style="font-size:18px;">public static void main(String[] args) {
//建立一個HashSet的集合
HashSet<Student> hs = new HashSet<Student>();
Student s1 = new Student("張三", 19); //建立學生物件
Student s2 = new Student("李四", 17);
Student s3 = new Student("小明", 18);
Student s4 = new Student("小紅", 22);
Student s5 = new Student("李四", 17);
hs.add(s1); //增加成員
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
for (Student student : hs) {
System.out.println(student);
}</span>
執行上面的程式我們發現,咦,怎麼有兩個 "李四",17 ,這是因為沒有重寫HashCode()方法和equals()方法,導致元素不是唯一的,解決方案就是在Student類中重寫HashCode()方法和equals()方法即可。
自動重寫HashCode()方法和equals()方法步驟:右擊選擇Source,找到Generate hashCode() and equals(),點選去,全選確定即可,系統會自動幫你重寫。程式碼入下:
<span style="font-size:18px;">@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;
}</span>
執行後發現李四隻剩一個了,這是因為重寫了HashCode()方法和equals()方法,保證了元素的唯一性。下面是TreeSet的:
<span style="font-size:18px;">public static void main(String[] args) {
//建立一個TreeSet的集合
TreeSet<Student> hs = new TreeSet<Student>();
Student s1 = new Student("張三", 19); //建立學生物件
Student s2 = new Student("李四", 17);
Student s3 = new Student("小明", 18);
Student s4 = new Student("小紅", 22);
Student s5 = new Student("李四", 17);
hs.add(s1); //增加成員
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
for (Student student : hs) {
System.out.println(student);
}
}</span>
執行上面的程式碼會發現error:Exception in thread "main" java.lang.ClassCastException.這又是怎麼回事?這是因為
TreeSet通過Compareable介面的compareTo()方法來保證元素的唯一性。可以通過下面兩種方式來解決:
1.自定義類(Student)繼承Comparable介面重寫compareTo()方法來實現
以上面Student類為例,按年齡從小到大排序
<span style="font-size:18px;"> @Override
public int compareTo(Student o) {
if((this.getAge()-o.getAge())>0){
return 1;
}else if((this.getAge()-o.getAge())<0){
return -1;
}else
return 0;
}</span>
對於這種方式,TreeSet採用的構造器應當是無參的,也就是使用元素的自然順序對元素進行排序。
2.建立set集合的時候,傳入Comparator進行排序,進行排序,也叫作比較器排序
public static void main(String[] args) {
//建立一個TreeSet的集合
TreeSet<Student> hs = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num1 = o1.getAge() - o2.getAge();
int num2 = num1==0?o1.getName().compareTo(o2.getName()):num1;
return num2;
}
});
Student s1 = new Student("張三", 19); //建立學生物件
Student s2 = new Student("李四", 17);
Student s3 = new Student("小明", 18);
Student s4 = new Student("小紅", 22);
Student s5 = new Student("李四", 17);
hs.add(s1); //增加成員
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
for (Student student : hs) {
System.out.println(student);
}
}
這裡使用了內部類,也達到了同樣的目的。