16 API-集合(List的子類(ArrayList_Vector_LinkedList,集合巢狀遍歷),JDK5新特性(泛型,增強for迴圈,靜態匯入,可變引數)
1:List的子類(掌握)
(1)List的子類特點ArrayList:
底層資料結構是陣列,查詢快,增刪慢
執行緒不安全,效率高
Vector:
底層資料結構是陣列,查詢快,增刪慢
執行緒安全,效率低
LinkedList:
底層資料結構是連結串列,查詢慢,增刪快
執行緒不安全,效率高
(2)ArrayList
A:沒有特有功能需要學習B:案例
a:ArrayList儲存字串並遍歷
b:ArrayList儲存自定義物件並遍歷
(3)Vector
A:有特有功能a:新增
public void addElement(E obj)--add()
b:獲取
public E elementAt(int index)--get()
public Enumeration<E> elements()-- iterator()
* boolean hasMoreElements() ----hasNext()
* Object nextElement()-------next()
a:Vector儲存字串並遍歷
b:Vector儲存自定義物件並遍歷
public class VectorDemo { public static void main(String[] args) { // 建立集合物件 Vector v = new Vector(); // 新增功能 v.addElement("hello"); v.addElement("world"); v.addElement("java"); // 遍歷 for (int x = 0; x < v.size(); x++) { String s = (String) v.elementAt(x); System.out.println(s); } System.out.println("------------------"); Enumeration en = v.elements(); // 返回的是實現類的物件 while (en.hasMoreElements()) { String s = (String) en.nextElement(); System.out.println(s); } } }
(4)LinkedList
A:有特有功能a:新增
addFirst()
addLast()
b:刪除
removeFirst()
removeLast()
c:獲取
getFirst()
getLast()
B:案例
a:LinkedList儲存字串並遍歷
b:LinkedList儲存自定義物件並遍歷
(5)案例:
A:去除集合中的多個字串的重複元素
如果字串的內容相同,即為重複元素
兩種思路
1.建立一個新集合 ,往裡面新增舊集合元素,新增時候判定是否equals, 加或者不加
import java.util.ArrayList; import java.util.Iterator; /* * ArrayList去除集合中字串的重複值(字串的內容相同) * * 分析: * A:建立集合物件 * B:新增多個字串元素(包含內容相同的) * C:建立新集合 * D:遍歷舊集合,獲取得到每一個元素 * E:拿這個元素到新集合去找,看有沒有 * 有:不搭理它 * 沒有:就新增到新集合 * F:遍歷新集合 */ public class ArrayListDemo { public static void main(String[] args) { // 建立集合物件 ArrayList array = new ArrayList(); // 新增多個字串元素(包含內容相同的) array.add("hello"); array.add("world"); array.add("java"); array.add("world"); array.add("java"); array.add("world"); array.add("world"); array.add("world"); array.add("world"); array.add("java"); array.add("world"); // 建立新集合 ArrayList newArray = new ArrayList(); // 遍歷舊集合,獲取得到每一個元素 Iterator it = array.iterator(); while (it.hasNext()) { String s = (String) it.next(); // 拿這個元素到新集合去找,看有沒有 if (!newArray.contains(s)) { newArray.add(s); } } // 遍歷新集合 for (int x = 0; x < newArray.size(); x++) { String s = (String) newArray.get(x); System.out.println(s); } } }
2.(如果不建立新集合)選擇排序內外迴圈比較equals
如果相同 就刪除remove這個,同時內迴圈自增要y--復位(如果同時N個重複會漏算)
import java.util.ArrayList;
import java.util.Iterator;
/*
* 需求:ArrayList去除集合中字串的重複值(字串的內容相同)
* 要求:不能建立新的集合,就在以前的集合上做。
*/
public class ArrayListDemo2 {
public static void main(String[] args) {
// 建立集合物件
ArrayList array = new ArrayList();
// 新增多個字串元素(包含內容相同的)
array.add("hello");
array.add("world");
array.add("java");
array.add("world");
array.add("java");
array.add("world");
array.add("world");
array.add("world");
array.add("world");
array.add("java");
array.add("world");
// 由選擇排序思想引入,我們就可以通過這種思想做這個題目
// 拿0索引的依次和後面的比較,有就把後的幹掉
// 同理,拿1索引...
for (int x = 0; x < array.size() - 1; x++) {
for (int y = x + 1; y < array.size(); y++) {
if (array.get(x).equals(array.get(y))) {
array.remove(y);
y--;
}
}
}
// 遍歷集合
Iterator it = array.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
}
}
B:去除集合中的多個自定義物件的重複元素
如果自定義物件的成員變數值都相同,即為重複元素
學生類略
import java.util.ArrayList;
import java.util.Iterator;
/*
* 需求:去除集合中自定義物件的重複值(物件的成員變數值都相同)
*
* 我們按照和字串一樣的操作,發現出問題了。
* 為什麼呢?
* 我們必須思考哪裡會出問題?
* 通過簡單的分析,我們知道問題出現在了判斷上。
* 而這個判斷功能是集合自己提供的,所以我們如果想很清楚的知道它是如何判斷的,就應該去看原始碼。
* contains()方法的底層依賴的是equals()方法。
* 而我們的學生類中沒有equals()方法,這個時候,預設使用的是它父親Object的equals()方法
* Object()的equals()預設比較的是地址值,所以,它們進去了。因為new的東西,地址值都不同。
* 按照我們自己的需求,比較成員變數的值,重寫equals()即可。
* 自動生成即可。
*/
public class ArrayListDemo3 {
public static void main(String[] args) {
// 建立集合物件
ArrayList array = new ArrayList();
// 建立學生物件
Student s1 = new Student("林青霞", 27);
Student s2 = new Student("林志玲", 40);
Student s3 = new Student("鳳姐", 35);
Student s4 = new Student("芙蓉姐姐", 18);
Student s5 = new Student("翠花", 16);
Student s6 = new Student("林青霞", 27);
Student s7 = new Student("林青霞", 18);
// 新增元素
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
array.add(s5);
array.add(s6);
array.add(s7);
// 建立新集合
ArrayList newArray = new ArrayList();
// 遍歷舊集合,獲取得到每一個元素
Iterator it = array.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
// 拿這個元素到新集合去找,看有沒有
if (!newArray.contains(s)) {
newArray.add(s);
}
}
// 遍歷新集合
for (int x = 0; x < newArray.size(); x++) {
Student s = (Student) newArray.get(x);
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
C:用LinkedList模擬一個棧資料結構的集合類,並測試。
你要定義一個集合類,只不過內部可以使用LinkedList來實現。
思路:棧資料結構特點先進後出,利用LinkedList的特有方法addFirst()及removeFirst()來體現。
第一步 自定義棧集合MyStack
import java.util.LinkedList;
/**
* 自定義的棧集合
*
* @author 風清揚
* @version V1.0
*/
public class MyStack {
private LinkedList link;
public MyStack() {
link = new LinkedList();
}
public void add(Object obj) {
link.addFirst(obj);
}
public Object get() {
// return link.getFirst(); 如果是這個都是java 每次都是第一個 沒有彈棧
return link.removeFirst();
}
public boolean isEmpty() {
return link.isEmpty();
}
}
第二部 測試
/*
* MyStack的測試
*/
public class MyStackDemo {
public static void main(String[] args) {
// 建立集合物件
MyStack ms = new MyStack();
// 新增元素
ms.add("hello");
ms.add("world");
ms.add("java");
// System.out.println(ms.get());
// System.out.println(ms.get());
// System.out.println(ms.get());
// NoSuchElementException
// System.out.println(ms.get());
while(!ms.isEmpty()){
System.out.println(ms.get());
}
}
}
2:泛型(掌握)
(1)泛型概述是一種把明確型別的工作推遲到建立物件或者呼叫方法的時候才去明確的特殊的型別。
(2)格式:
<資料型別> <T>等
注意:該資料型別只能是引用型別。
(3)好處:A:把執行時期的問題提前到了編譯期間
B:避免了強制型別轉換
C:優化了程式設計,解決了黃色警告線問題,讓程式更安全
(4)泛型的前世今生
A:泛型的由來
Object型別作為任意型別的時候,在向下轉型的時候,會隱含一個轉型問題
B:泛型類
•把泛型定義在類上 •格式:public class 類名<泛型型別1,…> •注意:泛型型別必須是引用型別C:泛型方法
•把泛型定義在方法上 •格式:public <泛型型別> 返回型別 方法名(泛型型別 .)D:泛型介面 如果類,介面,抽象類後面跟的有<E>就說要使用泛型。一般來說就是在集合中使用
•把泛型定義在介面上 •格式:public interface 介面名<泛型型別1…>E:泛型高階萬用字元
? 任意型別,如果沒有明確,那麼就是Object以及任意的Java類了
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
// 泛型如果明確的寫的時候,前後必須一致
Collection<Object> c1 = new ArrayList<Object>();
// Collection<Object> c2 = new ArrayList<Animal>();//報錯
// Collection<Object> c3 = new ArrayList<Dog>(); //報錯
// Collection<Object> c4 = new ArrayList<Cat>(); //報錯
// ?表示任意的型別都是可以的
Collection<?> c5 = new ArrayList<Object>();
Collection<?> c6 = new ArrayList<Animal>();
Collection<?> c7 = new ArrayList<Dog>();
Collection<?> c8 = new ArrayList<Cat>();
? extends E 向下限定,E及其子類
// ? extends E:向下限定,E及其子類
// Collection<? extends Animal> c9 = new ArrayList<Object>();//報錯 Animal的父類Object不行 向下限定了
Collection<? extends Animal> c10 = new ArrayList<Animal>();
Collection<? extends Animal> c11 = new ArrayList<Dog>();
Collection<? extends Animal> c12 = new ArrayList<Cat>();
? super E 向上限定,E極其父類
// ? super E:向上限定,E極其父類
Collection<? super Animal> c13 = new ArrayList<Object>();
Collection<? super Animal> c14 = new ArrayList<Animal>();
// Collection<? super Animal> c15 = new ArrayList<Dog>();//報錯只能Animal或者Animal的父類 向上限定了
// Collection<? super Animal> c16 = new ArrayList<Cat>();//報錯只能Animal或者Animal的父類 向上限定了
(5)我們在哪裡使用呢?
一般是在集合中使用。
3:增強for迴圈(掌握)
JDK5的新特性:自動拆裝箱,泛型,增強for,靜態匯入,可變引數,列舉
(1)是for迴圈的一種
簡化陣列和Collection集合的遍歷public interface Iterable<T> 實現這個介面允許物件成為 "foreach" 語句的目標。
(2)格式:
* for(元素資料型別 變數 : 陣列或者Collection集合) {
* 使用變數即可,該變數就是元素
* }
(3)好處:
簡化了陣列和集合的遍歷
(4)弊端
增強for迴圈的目標不能為null。建議在使用前,先判斷是否為null。
4:靜態匯入(瞭解)
(1)可以匯入到方法級別的匯入(2)格式:
import static 包名....類名.方法名;
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import static java.lang.Math.max;
A:方法必須是靜態的
B:如果多個類下有同名的方法,就不好區分了,還得加上字首。
所以一般我們並不使用靜態匯入,但是一定要能夠看懂。
5:可變引數(掌握)
(1)如果我們在寫方法的時候,引數個數不明確,就應該定義可變引數。(2)格式:
修飾符 返回值型別 方法名(資料型別... 變數) {}
注意:
A:該變數其實是一個數組名
B:如果一個方法有多個引數,並且有可變引數,可變引數必須在最後
(3)Arrays工具類的一個方法
asList()把陣列轉成集合。
public static <T> List<T> asList(T... a)
List<String> list = Arrays.asList("hello", "world", "java");
注意:這個集合的長度不能改變。
package cn.itcast_03;
import java.util.Arrays;
import java.util.List;
/*
* public static <T> List<T> asList(T... a):把陣列轉成集合
*
* 注意事項:
* 雖然可以把陣列轉成集合,但是集合的長度不能改變。
*/
public class ArraysDemo {
public static void main(String[] args) {
// 定義一個數組
// String[] strArray = { "hello", "world", "java" };
// List<String> list = Arrays.asList(strArray);
List<String> list = Arrays.asList("hello", "world", "java");
// UnsupportedOperationException
// list.add("javaee");
// UnsupportedOperationException
// list.remove(1);
list.set(1, "javaee");
for (String s : list) {
System.out.println(s);
}
}
}
6:練習(掌握)
A:集合的巢狀遍歷
1.學生類(略)
import java.util.ArrayList;
/*
* 集合的巢狀遍歷
* 需求:
* 我們班有學生,每一個學生是不是一個物件。所以我們可以使用一個集合表示我們班級的學生。ArrayList<Student>
* 但是呢,我們旁邊是不是還有班級,每個班級是不是也是一個ArrayList<Student>。
* 而我現在有多個ArrayList<Student>。也要用集合儲存,怎麼辦呢?
* 就是這個樣子的:ArrayList<ArrayList<Student>>
*/
public class ArrayListDemo {
public static void main(String[] args) {
// 建立大集合
ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>();
// 建立第一個班級的學生集合
ArrayList<Student> firstArrayList = new ArrayList<Student>();
// 建立學生
Student s1 = new Student("唐僧", 30);
Student s2 = new Student("孫悟空", 29);
Student s3 = new Student("豬八戒", 28);
Student s4 = new Student("沙僧", 27);
Student s5 = new Student("白龍馬", 26);
// 學生進班
firstArrayList.add(s1);
firstArrayList.add(s2);
firstArrayList.add(s3);
firstArrayList.add(s4);
firstArrayList.add(s5);
// 把第一個班級儲存到學生系統中
bigArrayList.add(firstArrayList);
// 建立第二個班級的學生集合
ArrayList<Student> secondArrayList = new ArrayList<Student>();
// 建立學生
Student s11 = new Student("諸葛亮", 30);
Student s22 = new Student("司馬懿", 28);
Student s33 = new Student("周瑜", 26);
// 學生進班
secondArrayList.add(s11);
secondArrayList.add(s22);
secondArrayList.add(s33);
// 把第二個班級儲存到學生系統中
bigArrayList.add(secondArrayList);
// 建立第三個班級的學生集合
ArrayList<Student> thirdArrayList = new ArrayList<Student>();
// 建立學生
Student s111 = new Student("宋江", 40);
Student s222 = new Student("吳用", 35);
Student s333 = new Student("高俅", 30);
Student s444 = new Student("李師師", 22);
// 學生進班
thirdArrayList.add(s111);
thirdArrayList.add(s222);
thirdArrayList.add(s333);
thirdArrayList.add(s444);
// 把第三個班級儲存到學生系統中
bigArrayList.add(thirdArrayList);
// 遍歷集合
for (ArrayList<Student> array : bigArrayList) {
for (Student s : array) {
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
}
B:產生10個1-20之間的隨機數,要求隨機數不能重複
import java.util.ArrayList;
import java.util.Random;
/*
* 獲取10個1-20之間的隨機數,要求不能重複
*
* 用陣列實現,但是陣列的長度是固定的,長度不好確定。
* 所以我們使用集合實現。
*
* 分析:
* A:建立產生隨機數的物件
* B:建立一個儲存隨機數的集合。
* C:定義一個統計變數。從0開始。
* D:判斷統計遍歷是否小於10
* 是:先產生一個隨機數,判斷該隨機數在集合中是否存在。
* 如果不存在:就新增,統計變數++。
* 如果存在:就不搭理它。
* 否:不搭理它
* E:遍歷集合
*/
public class RandomDemo {
public static void main(String[] args) {
// 建立產生隨機數的物件
Random r = new Random();
// 建立一個儲存隨機數的集合。
ArrayList<Integer> array = new ArrayList<Integer>();
// 定義一個統計變數。從0開始。
int count = 0;
// 判斷統計遍歷是否小於10
while (count < 10) {
//先產生一個隨機數
int number = r.nextInt(20) + 1;
//判斷該隨機數在集合中是否存在。
if(!array.contains(number)){
//如果不存在:就新增,統計變數++。
array.add(number);
count++;
}
}
//遍歷集合
for(Integer i : array){
System.out.println(i);
}
}
}
C:鍵盤錄入多個數據,以0結束,並在控制檯輸出最大值
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
/*
* 鍵盤錄入多個數據,以0結束,要求在控制檯輸出這多個數據中的最大值
*
* 分析:
* A:建立鍵盤錄入資料物件
* B:鍵盤錄入多個數據,我們不知道多少個,所以用集合儲存
* C:以0結束,這個簡單,只要鍵盤錄入的資料是0,我就不繼續錄入資料了
* D:把集合轉成陣列
* E:對陣列排序
* F:獲取該陣列中的最大索引的值
*/
public class ArrayListDemo {
public static void main(String[] args) {
// 建立鍵盤錄入資料物件
Scanner sc = new Scanner(System.in);
// 鍵盤錄入多個數據,我們不知道多少個,所以用集合儲存
ArrayList<Integer> array = new ArrayList<Integer>();
// 以0結束,這個簡單,只要鍵盤錄入的資料是0,我就不繼續錄入資料了
while (true) {
System.out.println("請輸入資料:");
int number = sc.nextInt();
if (number != 0) {
array.add(number);
} else {
break;
}
}
// 把集合轉成陣列
// public <T> T[] toArray(T[] a)
Integer[] i = new Integer[array.size()];
// Integer[] ii = array.toArray(i);
array.toArray(i);
// System.out.println(i);
// System.out.println(ii);
// 對陣列排序
// public static void sort(Object[] a)
Arrays.sort(i);
// 獲取該陣列中的最大索引的值
System.out.println("陣列是:" + arrayToString(i) + "最大值是:"
+ i[i.length - 1]);
}
public static String arrayToString(Integer[] i) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int x = 0; x < i.length; x++) {
if (x == i.length - 1) {
sb.append(i[x]);
} else {
sb.append(i[x]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
7:要掌握的程式碼
集合儲存元素,加入泛型,並可以使用增強for遍歷。