1. 程式人生 > >java中List與Set的常用用法

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的特點,底層資料結構是連結串列,所以它的增刪速度快,查詢速度慢。執行緒不安全、效率高。

新建一個測試學生類,這裡只說引用型別,不討論基本型別,後面不再論述。

<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>
鑑於篇幅原因,這裡只給出ArrayList的程式碼,因為LinkedList和ArrayList一樣的。
<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);
		}
	}
這裡使用了內部類,也達到了同樣的目的。