1. 程式人生 > 實用技巧 >第五章 泛型&集合

第五章 泛型&集合

5.1、泛型

概述:泛型是是JDK5中引入的特性,它提供了編譯時型別安全檢測機制,該機制允許在編譯時檢測到非法的型別,它的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。

泛型類:

// 格式:修飾符 class 類名<型別> { }
class Generic<T> {
	private T t;

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
}

public class Main {
	public static void main(String[] args) {
		Generic<String> g1 = new Generic<String>();
		g1.setT("String");
		System.out.println(g1.getT());
		Generic<Integer> g2 = new Generic<Integer>();
		g2.setT(100);
		System.out.println(g2.getT());
		Generic<Boolean> g3 = new Generic<Boolean>();
		g3.setT(true);
		System.out.println(g3.getT());
	}
}

泛型方法:

// 格式:修飾符 <型別> 返回值型別 方法名(型別 變數名) { }
class Generic {
	public <T> void show(T t) {
		System.out.println(t);
	}
}

public class Main {
	public static void main(String[] args) {
		Generic g = new Generic();
		g.show("String");
		g.show(100);
		g.show(true);
	}
}

泛型介面:

// 修飾符 interface 介面名<型別> { }
interface Generic<T> {
	void show(T t);
}

class GenericImpl<T> implements Generic<T> {
	@Override
	public void show(T t) {
		System.out.println(t);
	}
}

public class Main {
	public static void main(String[] args) {
		Generic<String> g1 = new GenericImpl<String>();
		g1.show("String");
		Generic<Integer> g2 = new GenericImpl<Integer>();
		g2.show(30);
		Generic<Boolean> g3 = new GenericImpl<Boolean>();
		g3.show(true);
	}
}

型別萬用字元:

型別萬用字元:<?>
    List<?>:表示元素型別未知的List,它的元素可以匹配任何的型別
    
型別萬用字元上限:<? extends 型別>
    List<? extends Number>:它表示的型別是Number或者其子型別
    
型別萬用字元下限:<? super 型別>
    List<? super Number>:它表示的型別是Number或者其父型別 

可變引數:

public class Main {
	public static void main(String[] args) {
		System.out.println(sum(10));
		System.out.println(sum(10, 20));
		System.out.println(sum(10, 20, 30));
		System.out.println(sum(10, 20, 30, 40));
		System.out.println(sum(10, 20, 30, 40, 50));
		System.out.println(sum(10, 20, 30, 40, 50, 60));
		System.out.println(sum(10, 20, 30, 40, 50, 60, 70));
		System.out.println(sum(10, 20, 30, 40, 50, 60, 70, 80));
		System.out.println(sum(10, 20, 30, 40, 50, 60, 70, 80, 90));
		System.out.println(sum(10, 20, 30, 40, 50, 60, 70, 80, 90, 100));
	}

	// 格式:修飾符 返回值型別 方法名(資料型別… 變數名) { }
	public static int sum(int... a) {
		int sum = 0;
		for (int i : a) {
			sum += i;
		}
		return sum;
	}
}

5.2、集合

概述:提供一種可變的儲存模型,儲存的資料容量可以隨時發生改變

體系:

5.2.1、Collection介面

子介面特點:

  1. List介面:按照順序存取,元素可以重複,有索引,可使用迭代器、增強for迴圈、普通for迴圈遍歷
  2. Set介面:不按照順序存取,元素不可以重複,沒有索引,可使用迭代器、增強for迴圈遍歷

通用方法:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Main {
	public static void main(String[] args) {
		// 建立集合
		Collection<String> collection = new ArrayList<String>();

		// 新增元素
		collection.add("張三");
		collection.add("張三");
		collection.add("李四");
		collection.add("李四");
		collection.add("王五");
		collection.add("王五");
		System.out.println(collection.toString());

		// 移除元素
		collection.remove("張三");
		System.out.println(collection.toString());

		// 判斷元素
		boolean isContains = collection.contains("李四");
		System.out.println(isContains);

		// 判斷集合是否為空
		boolean isEmpty = collection.isEmpty();
		System.out.println(isEmpty);

		// 獲取集合元素個數
		int size = collection.size();
		System.out.println(size);

		// 用迭代器遍歷集合
		Iterator<String> iterator = collection.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}

		// 用增強for迴圈遍歷
		for (String s : collection) {
			System.out.println(s);
		}

		// 新增另外集合元素
		Collection<String> c = new ArrayList<String>();
		c.add("小可愛");
		c.add("大可愛");
		collection.addAll(c);
		System.out.println(collection.toString());

		// 清空集合所有元素
		collection.clear();
		System.out.println(collection.toString());
	}
}

5.2.2、List介面

子類特點:

  1. ArrayList集合:底層是陣列結構實現,查詢快、增刪慢
  2. LinkedList集合:底層是連結串列結構實現,查詢慢、增刪快

通用方法:

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Main {
	public static void main(String[] args) {
		// 建立集合
		List<String> list = new ArrayList<String>();

		// 新增元素
		list.add("張三");
		list.add("張三");
		list.add("李四");
		list.add("李四");
		list.add("王五");
		list.add("王五");
		System.out.println(list.toString());

		// List獨有方法:E get(int index)
		String s = list.get(0);
		System.out.println(s);

		// List獨有方法:E set(int index, E element)
		list.set(2, "xiaoqi");
		System.out.println(list.toString());

		// List獨有方法:ListIterator<E> listIterator()
		ListIterator<String> listIterator = list.listIterator();
		// 使用列表迭代器:從前向後迭代
		while (listIterator.hasNext()) {
			System.out.println(listIterator.next());
		}
		// 使用列表迭代器:從後向前迭代
		while (listIterator.hasPrevious()) {
			System.out.println(listIterator.previous());
		}

		// List獨有遍歷:普通for迴圈遍歷
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}
}

注意事項:

LinkedList集合的特有方法:

方法 說明
public void addFirst(E e) 在該列表開頭插入指定的元素
public void addLast(E e) 在該列表末尾追加指定的元素
public E getFirst() 返回此列表中的第一個元素
public E getLast() 返回此列表中的最後一個元素
public E removeFirst() 從此列表中刪除並返回第一個元素
public E removeLast() 從此列表中刪除並返回最後一個元素

5.2.3、Set介面

子類特點:

  1. HashSet集合:底層由雜湊表支撐,元素存取無序,物件新增需要重寫hashCode和equals方法
  2. TreeSet集合:底層由二叉樹支撐,元素順序存取,物件排序需要繼承Comparable介面重寫compareTo方法、或者使用Comparator初始化

HashSet演示:

import java.util.Collection;
import java.util.HashSet;

class Student {
	private String name;
	private Integer age;

	public Student() {
		super();
	}

	public Student(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		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 == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}

public class Main {
	public static void main(String[] args) {
		// 建立集合
		Collection<Student> collection = new HashSet<Student>();

		// 新增元素
		collection.add(new Student("張三", 20));
		collection.add(new Student("張三", 20));
		collection.add(new Student("李四", 21));
		collection.add(new Student("李四", 21));
		collection.add(new Student("王五", 22));
		collection.add(new Student("王五", 22));
		System.out.println(collection.toString());
	}
}

TreeSet演示:按照年齡從小到大排序,年齡相同時,按照姓名的字母順序排序

import java.util.Collection;
import java.util.Comparator;
import java.util.TreeSet;

class Student {
	private String name;
	private Integer age;

	public Student() {
		super();
	}

	public Student(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

public class Main {
	public static void main(String[] args) {
		// 建立集合
		Collection<Student> collection = new TreeSet<Student>(new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				// 主要條件
				int sort1 = s1.getAge() - s2.getAge();
				// 次要條件
				int sort2 = sort1 == 0 ? s1.getName().compareTo(s2.getName()) : sort1;
				return sort2;
			}
		});

		// 新增元素
		collection.add(new Student("王五", 22));
		collection.add(new Student("王五", 22));
		collection.add(new Student("張三1", 20));
		collection.add(new Student("張三0", 20));
		collection.add(new Student("李四0", 18));
		collection.add(new Student("李四1", 18));
		System.out.println(collection.toString());
	}
}

5.2.4、Map介面

介面特點:

  1. 鍵值對對映關係
  2. 一個鍵對應一個值,鍵不可以重複,值可以重複
  3. 凡是物件作為HashMap的鍵時,物件新增需要重寫hashCode和equals方法

通用方法:

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Main {
	public static void main(String[] args) {
		// 建立集合
		Map<String, String> map = new HashMap<String, String>();

		// 新增元素
		map.put("呂布", "貂蟬");
		map.put("項羽", "虞姬");
		map.put("郭靖", "黃蓉");
		map.put("後裔", "嫦娥");
		System.out.println(map.toString());

		// 刪除元素
		map.remove("郭靖");
		System.out.println(map.toString());

		// 判斷集合是否包含指定鍵
		boolean containsKey = map.containsKey("呂布");
		System.out.println(containsKey);

		// 判斷集合是否包含指定值
		boolean containsValue = map.containsValue("貂蟬");
		System.out.println(containsValue);

		// 判斷集合是否為空
		boolean isEmpty = map.isEmpty();
		System.out.println(isEmpty);

		// 獲取集合元素個數
		int size = map.size();
		System.out.println(size);

		// 清空集合所有元素
		map.clear();
		System.out.println(map.toString());

		// 新增另外集合元素
		Map<String, String> m = new HashMap<String, String>();
		m.put("張三", "李四");
		m.put("王五", "小六");
		map.putAll(m);
		System.out.println(map.toString());

		// 根據鍵獲取值
		System.out.println(map.get("張三"));

		// 獲取所有鍵的集合
		Set<String> keySet = map.keySet();
		// 迭代器遍歷
		Iterator<String> keysIterator = keySet.iterator();
		while (keysIterator.hasNext()) {
			System.out.println(keysIterator.next());
		}
		// 增強for遍歷
		for (String key : keySet) {
			System.out.println(key);
		}

		// 獲取所有值的集合
		Collection<String> values = map.values();
		// 迭代器遍歷
		Iterator<String> valuesIterator = values.iterator();
		while (valuesIterator.hasNext()) {
			System.out.println(valuesIterator.next());
		}
		// 增強for遍歷
		for (String value : values) {
			System.out.println(value);
		}

		// 獲取所有鍵值對物件的集合
		Set<Entry<String, String>> entrySet = map.entrySet();
		// 迭代器遍歷
		Iterator<Entry<String, String>> entrySetIterator = entrySet.iterator();
		while (entrySetIterator.hasNext()) {
			Entry<String, String> entry = entrySetIterator.next();
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + ":" + value);
		}
		// 增強for遍歷
		for (Entry<String, String> entry : entrySet) {
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + ":" + value);
		}
	}
}

5.3、Collections類

描述:是針對集合操作的工具類

成員方法:

方法 描述
public static void sort(List list) 將指定的列表按升序排序
public static void reverse(List list) 反轉指定列表中元素的順序
public static void shuffle(List list) 使用預設的隨機源隨機排列指定的列表

示例程式碼:鬥地主洗牌

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class Main {
	public static void main(String[] args) {
		// 建立HashMap,鍵是編號,值是牌面
		HashMap<Integer, String> hm = new HashMap<Integer, String>();
		// 建立ArrayList,儲存編號
		ArrayList<Integer> array = new ArrayList<Integer>();
		// 建立花色陣列和點數陣列
		String[] colors = { "♦", "♣", "♥", "♠" };
		String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2" };
		// 從0開始往HashMap裡面儲存編號並存儲對應的牌面,同時往ArrayList裡面儲存編號
		int index = 0;
		for (String number : numbers) {
			for (String color : colors) {
				hm.put(index, color + number);
				array.add(index);
				index++;
			}
		}
		hm.put(index, "小王");
		array.add(index);
		index++;
		hm.put(index, "大王");
		array.add(index);
		// 洗牌(洗的是編號)
		Collections.shuffle(array);
		// 發牌(發的是編號)
		TreeSet<Integer> playerSet1 = new TreeSet<Integer>();
		TreeSet<Integer> playerSet2 = new TreeSet<Integer>();
		TreeSet<Integer> playerSet3 = new TreeSet<Integer>();
		TreeSet<Integer> dpSet = new TreeSet<Integer>();
		for (int i = 0; i < array.size(); i++) {
			int x = array.get(i);
			if (i >= array.size() - 3) {
				dpSet.add(x);
			} else if (i % 3 == 0) {
				playerSet1.add(x);
			} else if (i % 3 == 1) {
				playerSet2.add(x);
			} else if (i % 3 == 2) {
				playerSet3.add(x);
			}
		}
		// 呼叫看牌方法
		lookPoker("player1", playerSet1, hm);
		lookPoker("player2", playerSet2, hm);
		lookPoker("player3", playerSet3, hm);
		lookPoker("dp", dpSet, hm);
	}

	/**
	 * 看牌方法
	 * @param name 玩家名稱
	 * @param ts   牌面編號
	 * @param hm   牌面集合
	 */
	public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {
		System.out.print(name + ": ");
		for (Integer key : ts) {
			String poker = hm.get(key);
			System.out.print(poker + " ");
		}
		System.out.println();
	}
}