一、集合
前面我們保存多個數據使用的是數組,那么數組有不足的地方,我們分析一下
1.數組
2 集合?
- 數據類型也可以不一樣?
3.集合的框架體系?
- Java 的集合類很多,主要分為兩大類,如圖 :[背下來]
?
package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;/*** @author 林然* @version 1.0*/
public class Collection_ {public static void main(String[] args) {//1. 集合主要是兩組(單列集合 , 雙列集合)//2. Collection 接口有兩個重要的子接口 List 和Set , 他們的實現子類都是單列集合//3. Map 接口的實現子類 是雙列集合,存放的 K-V//4. 把老師梳理的兩張圖記住ArrayList arrayList =new ArrayList();arrayList.add("jack");arrayList.add("tom");HashMap hashMap =new HashMap();hashMap.put("No1","北京");}
}
4.Collection 接口和常用方法
4.1Collection 接口實現類的特點
- Collection 接口常用方法,以實現子類 ArrayList 來演示?
package com.hspedu.collection_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class CollectionMethod {@SuppressWarnings("all")public static void main(String[] args) {List list =new ArrayList();// add:添加單個元素list.add("jack");list.add(10);//這里相當于自動裝箱了,添加的實際是對象list.add(true);System.out.println("list="+list);// remove:刪除指定元素
//list.remove(0);//刪除第一個元素list.remove(true);//指定刪除某個元素System.out.println("list=" + list);// contains:查找元素是否存在System.out.println(list.contains("jack"));//T// size:獲取元素個數System.out.println(list.size());//2// isEmpty:判斷是否為空System.out.println(list.isEmpty());//F// clear:清空list.clear();System.out.println("list=" + list);// addAll:添加多個元素ArrayList list2=new ArrayList();list2.add("加油");list2.add("java大神");list.addAll(list2);System.out.println("list=" + list);// containsAll:查找多個元素是否都存在System.out.println(list.containsAll(list2));//T// removeAll:刪除多個元素list.add("聊齋");list.removeAll(list2);System.out.println("list=" + list);//[聊齋]}
}
4.2 Collection 接口遍歷元素方式 1-使用 Iterator(迭代器)
?
package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class CollectionIterator {public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book1("三國演義", "羅貫中", 10.1));col.add(new Book1("小李飛刀", "古龍", 5.1));col.add(new Book1("紅樓夢", "曹雪芹", 34.6));//現在老師希望能夠遍歷 col 集合//1. 先得到 col 對應的 迭代器Iterator iterator =col.iterator();//2. 使用 while 循環遍歷// while (iterator.hasNext()) {//判斷是否還有數據// //返回下一個元素,類型是 Object// Object obj = iterator.next();// System.out.println("obj=" + obj);// }//教大家一個快捷鍵,快速生成 while => itit//顯示所有的快捷鍵的的快捷鍵 ctrl + jwhile (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}//3. 當退出 while 循環后 , 這時 iterator 迭代器,指向最后的元素// iterator.next();//NoSuchElementException//4. 如果希望再次遍歷,需要重置我們的迭代器iterator = col.iterator();System.out.println("===第二次遍歷===");while (iterator.hasNext()) {Object obj = iterator.next();System.out.println("obj=" + obj);}}
}
@SuppressWarnings({"all"})
class Book1 {private String name;private String author;private double price;public Book1(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}@Overridepublic String toString() {return "Book1{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}
4.3 Collection 接口遍歷對象方式 2-for 循環增強
package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;/*** @author 林然* @version 1.0*/
public class CollectionFor {@SuppressWarnings("all")public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book1("三國演義", "羅貫中", 10.1));col.add(new Book1("小李飛刀", "古龍", 5.1));col.add(new Book1("紅樓夢", "曹雪芹", 34.6));//使用增強for循環for(Object k:col){System.out.println("book="+k);}}}
?4.4?課堂練習
package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class CollectionExercise {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add(new Dog("小黑", 3));list.add(new Dog("大黃", 100));list.add(new Dog("大壯", 8));//先使用for增強for (Object dog : list) {System.out.println("dog=" + dog);}//使用迭代器System.out.println("===使用迭代器來遍歷===");Iterator iterator = list.iterator();while (iterator.hasNext()) {Object dog = iterator.next();System.out.println("dog=" + dog);}}
}
/*** 創建 3個 Dog {name, age} 對象,放入到 ArrayList 中,賦給 List 引用* 用迭代器和增強for循環兩種方式來遍歷* 重寫Dog 的toString方法, 輸出name和age*/
class Dog {private String name;private int age;public Dog(String name, int age) {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;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", age=" + age +'}';}
}
?二、List?
1.List 接口和常用方法?
1.1??List 接口基本介紹
package com.hspedu.list_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class List_ {@SuppressWarnings("all")public static void main(String[] args) {//1. List 集合類中元素有序(即添加順序和取出順序一致)、且可重復 [案例]List list = new ArrayList();list.add("jack");list.add("tom");list.add("mary");list.add("lsl");list.add("tom");System.out.println("list=" + list);
//2. List 集合中的每個元素都有其對應的順序索引,即支持索引
// 索引是從 0 開始的System.out.println(list.get(3));//lsl
//3}
}
?1.2 List 接口的常用方法
package com.hspedu.list_;import java.util.ArrayList;
import java.util.List;/*** @author 林然* @version 1.0*/
public class ListMethod {@SuppressWarnings("all")public static void main(String[] args) {List list =new ArrayList();list.add("張三豐");list.add("賈寶玉");
// void add(int index, Object ele):在 index 位置插入 ele 元素//在 index = 1 的位置插入一個對象list.add(1, "林然");System.out.println("list=" + list);// boolean addAll(int index, Collection eles):從 index 位置開始將 eles 中的所有元素添加進來List list2 = new ArrayList();list2.add("jack");list2.add("tom");list.addAll(1, list2);System.out.println("list=" + list);// Object get(int index):獲取指定 index 位置的元素// int indexOf(Object obj):返回 obj 在集合中首次出現的位置System.out.println(list.indexOf("tom"));//2// int lastIndexOf(Object obj):返回 obj 在當前集合中末次出現的位置list.add("林然");System.out.println("list=" + list);System.out.println(list.lastIndexOf("林然"));// Object remove(int index):移除指定 index 位置的元素,并返回此元素list.remove(0);System.out.println("list=" + list);// Object set(int index, Object ele):設置指定 index 位置的元素為 ele , 相當于是替換. list.set(1, "瑪麗");System.out.println("list=" + list);// List subList(int fromIndex, int toIndex):返回從 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndexList returnlist = list.subList(0, 2);System.out.println("returnlist=" + returnlist);}
}
?1.3?List 接口課堂練習
package com.hspedu.list_;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class ListExercise {@SuppressWarnings({"all"})public static void main(String[] args) {/*添加10個以上的元素(比如String "hello" ),在2號位插入一個元素"韓順平教育",獲得第5個元素,刪除第6個元素,修改第7個元素,在使用迭代器遍歷集合,要求:使用List的實現類ArrayList完成。*/List list = new ArrayList();for (int i = 0; i < 12; i++) {list.add("hello" + i);}System.out.println("list=" + list);//在2號位插入一個元素"韓順平教育"list.add(1, "韓順平教育");System.out.println("list=" + list);//獲得第5個元素System.out.println("第五個元素=" + list.get(4));//刪除第6個元素list.remove(5);System.out.println("list=" + list);//修改第7個元素list.set(6, "三國演義");System.out.println("list=" + list);//在使用迭代器遍歷集合Iterator iterator = list.iterator();while (iterator.hasNext()) {Object obj = iterator.next();System.out.println("obj=" + obj);}}
}
?1.4?List 的三種遍歷方式 [ArrayList, LinkedList,Vector]
package com.hspedu.list_;import java.util.*;public class ListFor {@SuppressWarnings({"all"})public static void main(String[] args) {//List 接口的實現子類 Vector LinkedList//List list = new ArrayList();//List list = new Vector();List list = new LinkedList();list.add("jack");list.add("tom");list.add("魚香肉絲");list.add("北京烤鴨子");//遍歷//1. 迭代器Iterator iterator = list.iterator();while (iterator.hasNext()) {Object obj = iterator.next();System.out.println(obj);}System.out.println("=====增強for=====");//2. 增強forfor (Object o : list) {System.out.println("o=" + o);}System.out.println("=====普通for====");//3. 使用普通forfor (int i = 0; i < list.size(); i++) {System.out.println("對象=" + list.get(i));}}
}
?1.5?實現類的課堂練習 2
package com.hspedu.list_;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;@SuppressWarnings({"all"})
public class ListExercise02 {public static void main(String[] args) {//List list = new ArrayList();List list = new LinkedList();//List list = new Vector();list.add(new Book("紅樓夢", "曹雪芹", 100));list.add(new Book("西游記", "吳承恩", 10));list.add(new Book("水滸傳", "施耐庵", 19));list.add(new Book("三國", "羅貫中", 80));//list.add(new Book("西游記", "吳承恩", 10));//如何對集合進行排序//遍歷for (Object o : list) {System.out.println(o);}//冒泡排序sort(list);System.out.println("==排序后==");for (Object o : list) {System.out.println(o);}}//靜態方法//價格要求是從小到大public static void sort(List list) {int listSize = list.size();for (int i = 0; i < listSize - 1; i++) {for (int j = 0; j < listSize - 1 - i; j++) {//取出對象BookBook book1 = (Book) list.get(j);Book book2 = (Book) list.get(j + 1);if (book1.getPrice() > book2.getPrice()) {//交換list.set(j, book2);list.set(j + 1, book1);}}}}
}
package com.hspedu.list_;public class Book {private String name;private String author;private double price;public Book(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "名稱:" + name + "\t\t價格:" + price + "\t\t作者:" + author;}
}
2.ArrayList 底層結構和源碼分析
2.1?ArrayList 的注意事項
2.2?ArrayList 的底層操作機制源碼分析(重點,難點.)?
?3.Vector 底層結構和源碼剖析
3.1?Vector 的基本介紹
3.2?Vector 和 ArrayList 的比較?
4.LinkedList 底層結構?
4.1?LinkedList 的全面說明
4.2?LinkedList 的底層操作機制?
【這里其實就是涉及數據結構的知識點】
package com.hspedu.list_;public class LinkedList01 {public static void main(String[] args) {//模擬一個簡單的雙向鏈表Node jack = new Node("jack");Node tom = new Node("tom");Node hsp = new Node("老韓");//連接三個結點,形成雙向鏈表//jack -> tom -> hspjack.next = tom;tom.next = hsp;//hsp -> tom -> jackhsp.pre = tom;tom.pre = jack;Node first = jack;//讓first引用指向jack,就是雙向鏈表的頭結點Node last = hsp; //讓last引用指向hsp,就是雙向鏈表的尾結點//演示,從頭到尾進行遍歷System.out.println("===從頭到尾進行遍歷===");while (true) {if(first == null) {break;}//輸出first 信息System.out.println(first);first = first.next;}//演示,從尾到頭的遍歷System.out.println("====從尾到頭的遍歷====");while (true) {if(last == null) {break;}//輸出last 信息System.out.println(last);last = last.pre;}//演示鏈表的添加對象/數據,是多么的方便//要求,是在 tom --------- 老韓直接,插入一個對象 smith//1. 先創建一個 Node 結點,name 就是 smithNode smith = new Node("smith");//下面就把 smith 加入到雙向鏈表了smith.next = hsp;smith.pre = tom;hsp.pre = smith;tom.next = smith;//讓first 再次指向jackfirst = jack;//讓first引用指向jack,就是雙向鏈表的頭結點System.out.println("===從頭到尾進行遍歷===");while (true) {if(first == null) {break;}//輸出first 信息System.out.println(first);first = first.next;}last = hsp; //讓last 重新指向最后一個結點//演示,從尾到頭的遍歷System.out.println("====從尾到頭的遍歷====");while (true) {if(last == null) {break;}//輸出last 信息System.out.println(last);last = last.pre;}}
}//定義一個Node 類,Node 對象 表示雙向鏈表的一個結點
class Node {public Object item; //真正存放數據public Node next; //指向后一個結點public Node pre; //指向前一個結點public Node(Object name) {this.item = name;}public String toString() {return "Node name=" + item;}
}
?4.3?LinkedList 的增刪改查案例
package com.hspedu.list_;import java.util.Iterator;
import java.util.LinkedList;/*** @author 韓順平* @version 1.0*/
@SuppressWarnings({"all"})
public class LinkedListCRUD {public static void main(String[] args) {LinkedList linkedList = new LinkedList();linkedList.add(1);linkedList.add(2);linkedList.add(3);System.out.println("linkedList=" + linkedList);//演示一個刪除結點的linkedList.remove(); // 這里默認刪除的是第一個結點//linkedList.remove(2);System.out.println("linkedList=" + linkedList);//修改某個結點對象linkedList.set(1, 999);System.out.println("linkedList=" + linkedList);//得到某個結點對象//get(1) 是得到雙向鏈表的第二個對象Object o = linkedList.get(1);System.out.println(o);//999//因為LinkedList 是 實現了List接口, 遍歷方式System.out.println("===LinkeList遍歷迭代器====");Iterator iterator = linkedList.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println("next=" + next);}System.out.println("===LinkeList遍歷增強for====");for (Object o1 : linkedList) {System.out.println("o1=" + o1);}System.out.println("===LinkeList遍歷普通for====");for (int i = 0; i < linkedList.size(); i++) {System.out.println(linkedList.get(i));}//老韓源碼閱讀./* 1. LinkedList linkedList = new LinkedList();public LinkedList() {}2. 這時 linkeList 的屬性 first = null last = null3. 執行 添加public boolean add(E e) {linkLast(e);return true;}4.將新的結點,加入到雙向鏈表的最后void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}*//*老韓讀源碼 linkedList.remove(); // 這里默認刪除的是第一個結點1. 執行 removeFirstpublic E remove() {return removeFirst();}2. 執行public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}3. 執行 unlinkFirst, 將 f 指向的雙向鏈表的第一個結點拿掉private E unlinkFirst(Node<E> f) {// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}*/}
}
4.4?ArrayList 和 LinkedList 比較
三、Set?
1.Set 接口和常用方法?
1.1?Set 接口基本介紹
1.2?Set 接口的常用方法?
和 List 接口一樣 , Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一樣
1.3?Set 接口的遍歷方式
1.4?Set 接口的常用方法舉例?
package com.hspedu.set_;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;@SuppressWarnings({"all"})
public class SetMethod {public static void main(String[] args) {//老韓解讀//1. 以Set 接口的實現類 HashSet 來講解Set 接口的方法//2. set 接口的實現類的對象(Set接口對象), 不能存放重復的元素, 可以添加一個null//3. set 接口對象存放數據是無序(即添加的順序和取出的順序不一致)//4. 注意:取出的順序的順序雖然不是添加的順序,但是他的固定【就是每次得到的順序的固定的】.Set set = new HashSet();set.add("john");set.add("lucy");set.add("john");//重復,由于重復,只會有一個set.add("jack");set.add("hsp");set.add("mary");set.add(null);//set.add(null);//再次添加null,由于重復,只會有一個for(int i = 0; i <10;i ++) {System.out.println("set=" + set);}//遍歷//方式1: 使用迭代器System.out.println("=====使用迭代器====");Iterator iterator = set.iterator();while (iterator.hasNext()) {Object obj = iterator.next();System.out.println("obj=" + obj);}set.remove(null);//方式2: 增強forSystem.out.println("=====增強for====");for (Object o : set) {System.out.println("o=" + o);}//set 接口對象,不能通過索引來獲取}
}
2.HashSet
2.1?HashSet 的全面說明
package com.hspedu.set_;import java.util.HashSet;
import java.util.Set;@SuppressWarnings({"all"})
public class HashSet_ {public static void main(String[] args) {//老韓解讀//1. 構造器走的源碼/*public HashSet() {map = new HashMap<>();}2. HashSet 可以存放null ,但是只能有一個null,即元素不能重復*/Set hashSet = new HashSet();hashSet.add(null);hashSet.add(null);System.out.println("hashSet=" + hashSet);}
}
?2.2?HashSet 案例說明
package com.hspedu.set_;import java.util.HashSet;@SuppressWarnings({"all"})
public class HashSet01 {public static void main(String[] args) {HashSet set = new HashSet();//說明//1. 在執行add方法后,會返回一個boolean值//2. 如果添加成功,返回 true, 否則返回false//3. 可以通過 remove 指定刪除哪個對象System.out.println(set.add("john"));//TSystem.out.println(set.add("lucy"));//TSystem.out.println(set.add("john"));//FSystem.out.println(set.add("jack"));//TSystem.out.println(set.add("Rose"));//Tset.remove("john");System.out.println("set=" + set);//3個//set = new HashSet();System.out.println("set=" + set);//0//4 Hashset 不能添加相同的元素/數據?set.add("lucy");//添加成功set.add("lucy");//加入不了set.add(new Dog("tom"));//OKset.add(new Dog("tom"));//OkSystem.out.println("set=" + set);//在加深一下. 非常經典的面試題.//看源碼,做分析, 先給小伙伴留一個坑,以后講完源碼,你就了然//去看他的源碼,即 add 到底發生了什么?=> 底層機制.set.add(new String("hsp"));//okset.add(new String("hsp"));//加入不了.System.out.println("set=" + set);}
}
class Dog { //定義了Dog類private String name;public Dog(String name) {this.name = name;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +'}';}
}
?2.3?HashSet 底層機制說明
package com.hspedu.set_;@SuppressWarnings({"all"})
public class HashSetStructure {public static void main(String[] args) {//模擬一個HashSet的底層 (HashMap 的底層結構)//1. 創建一個數組,數組的類型是 Node[]//2. 有些人,直接把 Node[] 數組稱為 表Node[] table = new Node[16];//3. 創建結點Node john = new Node("john", null);table[2] = john;Node jack = new Node("jack", null);john.next = jack;// 將jack 結點掛載到johnNode rose = new Node("Rose", null);jack.next = rose;// 將rose 結點掛載到jackNode lucy = new Node("lucy", null);table[3] = lucy; // 把lucy 放到 table表的索引為3的位置.System.out.println("table=" + table);}
}
class Node { //結點, 存儲數據, 可以指向下一個結點,從而形成鏈表Object item; //存放數據Node next; // 指向下一個結點public Node(Object item, Node next) {this.item = item;this.next = next;}
}
?【在這里我們可以看到他用得是equals,由于字符串改寫了,其比較的是內容,之前的一個案例就在這里被解釋了】
【如果table沒到64,但是鏈表超過8,將會對table進行擴容】
?【下面的源碼更加說明了上面的結論】
package com.hspedu.set_;import java.util.HashSet;/*** @author 韓順平* @version 1.0*/
@SuppressWarnings({"all"})
public class HashSetSource {public static void main(String[] args) {HashSet hashSet = new HashSet();hashSet.add("java");//到此位置,第1次add分析完畢.hashSet.add("php");//到此位置,第2次add分析完畢hashSet.add("java");System.out.println("set=" + hashSet);/*對HashSet 的源碼解讀1. 執行 HashSet()public HashSet() {map = new HashMap<>();}2. 執行 add()public boolean add(E e) {//e = "java"return map.put(e, PRESENT)==null;//(static) PRESENT = new Object();}3.執行 put() , 該方法會執行 hash(key) 得到key對應的hash值 算法h = key.hashCode()) ^ (h >>> 16)public V put(K key, V value) {//key = "java" value = PRESENT 共享return putVal(hash(key), key, value, false, true);}4.執行 putValfinal V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i; //定義了輔助變量//table 就是 HashMap 的一個數組,類型是 Node[]//if 語句表示如果當前table 是null, 或者 大小=0//就是第一次擴容,到16個空間.if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//(1)根據key,得到hash 去計算該key應該存放到table表的哪個索引位置//并把這個位置的對象,賦給 p//(2)判斷p 是否為null//(2.1) 如果p 為null, 表示還沒有存放元素, 就創建一個Node (key="java",value=PRESENT)//(2.2) 就放在該位置 tab[i] = newNode(hash, key, value, null)if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {//一個開發技巧提示: 在需要局部變量(輔助變量)時候,在創建Node<K,V> e; K k; ////如果當前索引位置對應的鏈表的第一個元素和準備添加的key的hash值一樣//并且滿足 下面兩個條件之一://(1) 準備加入的key 和 p 指向的Node 結點的 key 是同一個對象//(2) p 指向的Node 結點的 key 的equals() 和準備加入的key比較后相同//就不能加入if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//再判斷 p 是不是一顆紅黑樹,//如果是一顆紅黑樹,就調用 putTreeVal , 來進行添加else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//如果table對應索引位置,已經是一個鏈表, 就使用for循環比較//(1) 依次和該鏈表的每一個元素比較后,都不相同, 則加入到該鏈表的最后// 注意在把元素添加到鏈表后,立即判斷 該鏈表是否已經達到8個結點// , 就調用 treeifyBin() 對當前這個鏈表進行樹化(轉成紅黑樹)// 注意,在轉成紅黑樹時,要進行判斷, 判斷條件// if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY(64))// resize();// 如果上面條件成立,先table擴容.// 只有上面條件不成立時,才進行轉成紅黑樹//(2) 依次和該鏈表的每一個元素比較過程中,如果有相同情況,就直接breakfor (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD(8) - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;//size 就是我們每加入一個結點Node(k,v,h,next), size++if (++size > threshold)resize();//擴容afterNodeInsertion(evict);return null;}*/}
}
2.4?HashSet 課堂練習 1
package com.hspedu.set_;import java.util.HashSet;
import java.util.Objects;/*** @author 林然* @version 1.0*/
public class HashSetExercise {@SuppressWarnings("all")public static void main(String[] args) {/**定義一個 Employee 類,該類包含:private 成員屬性 name,age 要求:創建 3 個 Employee 對象放入 HashSet 中當 name 和 age 的值相同時,認為是相同員工, 不能添加到 HashSet 集合中*/HashSet hashSet = new HashSet();hashSet.add(new Employee("milan", 18));//okhashSet.add(new Employee("smith", 28));//okhashSet.add(new Employee("milan", 18));//加入不成功System.out.println("hashSet=" + hashSet);}
}
//創建 Employee
class Employee{private String name;private int age;public Employee(String name, int age) {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;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employee employee = (Employee) o;return age == employee.age &&Objects.equals(name, employee.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
?2.5?HashSet 課后練習 2
3.LinkedHashSet?
3.1?LinkedHashSet 的全面說明
package com.hspedu.set_;import java.util.LinkedHashSet;
import java.util.Set;@SuppressWarnings({"all"})
public class LinkedHashSetSource {public static void main(String[] args) {//分析一下LinkedHashSet的底層機制Set set = new LinkedHashSet();set.add(new String("AA"));set.add(456);set.add(456);set.add(new Customer("劉", 1001));set.add(123);set.add("HSP");System.out.println("set=" + set);//1. LinkedHashSet 加入順序和取出元素/數據的順序一致//2. LinkedHashSet 底層維護的是一個LinkedHashMap(是HashMap的子類)//3. LinkedHashSet 底層結構 (數組table+雙向鏈表)//4. 添加第一次時,直接將 數組table 擴容到 16 ,存放的結點類型是 LinkedHashMap$Entry//5. 數組是 HashMap$Node[] 存放的元素/數據是 LinkedHashMap$Entry類型/*//繼承關系是在內部類完成.static class Entry<K,V> extends HashMap.Node<K,V> {Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);}}*/}
}
class Customer {private String name;private int no;public Customer(String name, int no) {this.name = name;this.no = no;}
}
3.2?LinkedHashSet 課后練習題
package com.hspedu.set_;import java.util.LinkedHashSet;
import java.util.Objects;@SuppressWarnings({"all"})
public class LinkedHashSetExercise {public static void main(String[] args) {LinkedHashSet linkedHashSet = new LinkedHashSet();linkedHashSet.add(new Car("奧拓", 1000));//OKlinkedHashSet.add(new Car("奧迪", 300000));//OKlinkedHashSet.add(new Car("法拉利", 10000000));//OKlinkedHashSet.add(new Car("奧迪", 300000));//加入不了linkedHashSet.add(new Car("保時捷", 70000000));//OKlinkedHashSet.add(new Car("奧迪", 300000));//加入不了System.out.println("linkedHashSet=" + linkedHashSet);}
}/*** Car 類(屬性:name,price), 如果 name 和 price 一樣,* 則認為是相同元素,就不能添加。 5min*/class Car {private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "\nCar{" +"name='" + name + '\'' +", price=" + price +'}';}//重寫equals 方法 和 hashCode//當 name 和 price 相同時, 就返回相同的 hashCode 值, equals返回t@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}
}
?四、Map
1.Map 接口和常用方法?
1.1?Map 接口實現類的特點 [很實用]
package com.hspedu.map_;import java.util.HashMap;
import java.util.Map;/*** @author 林然* @version 1.0*/
public class Map_ {@SuppressWarnings("all")public static void main(String[] args) {//老韓解讀 Map 接口實現類的特點, 使用實現類 HashMap//1. Map 與 Collection 并列存在。用于保存具有映射關系的數據:Key-Value(雙列元素)//2. Map 中的 key 和 value 可以是任何引用類型的數據,會封裝到 HashMap$Node 對象中//3. Map 中的 key 不允許重復,原因和 HashSet 一樣,前面分析過源碼. //4. Map 中的 value 可以重復//5. Map 的 key 可以為 null, value 也可以為 null ,注意 key 為 null,// 只能有一個,value 為 null ,可以多個//6. 常用 String 類作為 Map 的 key//7. key 和 value 之間存在單向一對一關系,即通過指定的 key 總能找到對應的 valueMap map =new HashMap();map.put("no1","林然");//k-vmap.put("no2","林然2");//k-vmap.put("no1","張三豐");//k-v 當有相同的 k , 就等價于替換.map.put("no3","張三豐");//k-vmap.put(null,null);//k-vmap.put(null,"abc");//k-v 當有相同的 k , 就等價于替換map.put("no4",null);//k-vmap.put(1, "趙敏");//k-vmap.put(new Object(), "金毛獅王");//k-v// 通過 get 方法,傳入 key ,會返回對應的 valueSystem.out.println(map.get("no2"));//林然System.out.println(map);}
}
package com.hspedu.map_;import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;@SuppressWarnings({"all"})
public class MapSource_ {public static void main(String[] args) {Map map = new HashMap();map.put("no1", "韓順平");//k-vmap.put("no2", "張無忌");//k-vmap.put(new Car(), new Person());//k-v//老韓解讀//1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null)//2. k-v 為了方便程序員的遍歷,還會 創建 EntrySet 集合 ,該集合存放的元素的類型 Entry, 而一個Entry// 對象就有k,v EntrySet<Entry<K,V>> 即: transient Set<Map.Entry<K,V>> entrySet;//3. entrySet 中, 定義的類型是 Map.Entry ,但是實際上存放的還是 HashMap$Node// 這時因為 static class Node<K,V> implements Map.Entry<K,V>//4. 當把 HashMap$Node 對象 存放到 entrySet 就方便我們的遍歷, 因為 Map.Entry 提供了重要方法// K getKey(); V getValue();Set set = map.entrySet();System.out.println(set.getClass());// HashMap$EntrySetfor (Object obj : set) {//System.out.println(obj.getClass()); //HashMap$Node//為了從 HashMap$Node 取出k-v//1. 先做一個向下轉型Map.Entry entry = (Map.Entry) obj;System.out.println(entry.getKey() + "-" + entry.getValue() );}Set set1 = map.keySet();System.out.println(set1.getClass());Collection values = map.values();System.out.println(values.getClass());}
}class Car {}class Person{}
1.2 常用方法
?
package com.hspedu.map_;import java.util.HashMap;
import java.util.Map;/*** @author 林然* @version 1.0*/public class MapMethod {public static void main(String[] args) {//演示 map 接口常用方法Map map = new HashMap();map.put("鄧超", new Book("", 100));//OKmap.put("鄧超", "孫儷");//替換-> 一會分析源碼map.put("王寶強", "馬蓉");//OKmap.put("宋喆", "馬蓉");//OKmap.put("劉令博", null);//OKmap.put(null, "劉亦菲");//OKmap.put("鹿晗", "關曉彤");//OKmap.put("hsp", "hsp 的老婆");System.out.println("map=" + map);
// remove:根據鍵刪除映射關系map.remove(null);System.out.println("map=" + map);
// get:根據鍵獲取值Object val = map.get("鹿晗");System.out.println("val=" + val);
// size:獲取元素個數System.out.println("k-v=" + map.size());
// isEmpty:判斷個數是否為 0System.out.println(map.isEmpty());//F
// clear:清除 k-v
//map.clear();System.out.println("map=" + map);
// containsKey:查找鍵是否存在System.out.println("結果=" + map.containsKey("hsp"));//T}
}class Book {private String name;private int num;public Book(String name, int num) {this.name = name;this.num = num;}
}
?1.3?Map 接口遍歷方法
package com.hspedu.map_;import java.util.*;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class MapFor {public static void main(String[] args) {Map map = new HashMap();map.put("鄧超", "孫儷");map.put("王寶強", "馬蓉");map.put("宋喆", "馬蓉");map.put("劉令博", null);map.put(null, "劉亦菲");map.put("鹿晗", "關曉彤");//第一組: 先取出 所有的 Key , 通過 Key 取出對應的 ValueSet keyset = map.keySet();//(1) 增強 forSystem.out.println("-----第一種方式-------");for (Object key : keyset) {System.out.println(key + "-" + map.get(key));}//(2) 迭代器System.out.println("----第二種方式--------");Iterator iterator = keyset.iterator();while (iterator.hasNext()) {Object key = iterator.next();System.out.println(key + "-" + map.get(key));}//第二組: 把所有的 values 取出Collection values = map.values();//這里可以使用所有的 Collections 使用的遍歷方法//(1) 增強 forSystem.out.println("---取出所有的 value 增強 for----");for (Object value : values) {System.out.println(value);}
//(2) 迭代器System.out.println("---取出所有的 value 迭代器----");Iterator iterator2 = values.iterator();while (iterator2.hasNext()){Object value = iterator2.next();System.out.println(value);}//第三組: 通過 EntrySet 來獲取 k-vSet entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增強 forSystem.out.println("----使用 EntrySet 的 for 增強(第 3 種)----");for (Object entry : entrySet) {
//將 entry 轉成 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}
//(2) 迭代器System.out.println("----使用 EntrySet 的 迭代器(第 4 種)----");Iterator iterator3 = entrySet.iterator();while (iterator3.hasNext()) {Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -實現-> Map.Entry (getKey,getValue)
//向下轉型 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}}
}
?1.4?Map 接口課堂練習
package com.hspedu.map_;import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;@SuppressWarnings({"all"})
public class MapExercise {public static void main(String[] args) {//完成代碼Map hashMap = new HashMap();//添加對象hashMap.put(1, new Emp("jack", 300000, 1));hashMap.put(2, new Emp("tom", 21000, 2));hashMap.put(3, new Emp("milan", 12000, 3));//遍歷2種方式//并遍歷顯示工資>18000的員工(遍歷方式最少兩種)//1. 使用keySet -> 增強forSet keySet = hashMap.keySet();System.out.println("====第一種遍歷方式====");for (Object key : keySet) {//先獲取valueEmp emp = (Emp) hashMap.get(key);if(emp.getSal() >18000) {System.out.println(emp);}}//2. 使用EntrySet -> 迭代器// 體現比較難的知識點// 慢慢品,越品越有味道.Set entrySet = hashMap.entrySet();System.out.println("======迭代器======");Iterator iterator = entrySet.iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry)iterator.next();//通過entry 取得key 和 valueEmp emp = (Emp) entry.getValue();if(emp.getSal() > 18000) {System.out.println(emp);}}}
}
/*** 使用HashMap添加3個員工對象,要求* 鍵:員工id* 值:員工對象** 并遍歷顯示工資>18000的員工(遍歷方式最少兩種)* 員工類:姓名、工資、員工id*/
class Emp {private String name;private double sal;private int id;public Emp(String name, double sal, int id) {this.name = name;this.sal = sal;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSal() {return sal;}public void setSal(double sal) {this.sal = sal;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Emp{" +"name='" + name + '\'' +", sal=" + sal +", id=" + id +'}';}
}
?2.Map 接口實現類-HashMap
2.1?HashMap 小結?
2.2?HashMap 底層機制及源碼剖析?
package com.hspedu.map_;import java.util.HashMap;@SuppressWarnings({"all"})
public class HashMapSource1 {public static void main(String[] args) {HashMap map = new HashMap();map.put("java", 10);//okmap.put("php", 10);//okmap.put("java", 20);//替換valueSystem.out.println("map=" + map);///*老韓解讀HashMap的源碼+圖解1. 執行構造器 new HashMap()初始化加載因子 loadfactor = 0.75HashMap$Node[] table = null2. 執行put 調用 hash方法,計算 key的 hash值 (h = key.hashCode()) ^ (h >>> 16)public V put(K key, V value) {//K = "java" value = 10return putVal(hash(key), key, value, false, true);}3. 執行 putValfinal V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;//輔助變量//如果底層的table 數組為null, 或者 length =0 , 就擴容到16if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//取出hash值對應的table的索引位置的Node, 如果為null, 就直接把加入的k-v//, 創建成一個 Node ,加入該位置即可if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;//輔助變量// 如果table的索引位置的key的hash相同和新的key的hash值相同,// 并 滿足(table現有的結點的key和準備添加的key是同一個對象 || equals返回真)// 就認為不能加入新的k-vif (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)//如果當前的table的已有的Node 是紅黑樹,就按照紅黑樹的方式處理e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {//如果找到的結點,后面是鏈表,就循環比較for (int binCount = 0; ; ++binCount) {//死循環if ((e = p.next) == null) {//如果整個鏈表,沒有和他相同,就加到該鏈表的最后p.next = newNode(hash, key, value, null);//加入后,判斷當前鏈表的個數,是否已經到8個,到8個,后//就調用 treeifyBin 方法進行紅黑樹的轉換if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash && //如果在循環比較過程中,發現有相同,就break,就只是替換value((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value; //替換,key對應valueafterNodeAccess(e);return oldValue;}}++modCount;//每增加一個Node ,就size++if (++size > threshold[12-24-48])//如size > 臨界值,就擴容resize();afterNodeInsertion(evict);return null;}5. 關于樹化(轉成紅黑樹)//如果table 為null ,或者大小還沒有到 64,暫時不樹化,而是進行擴容.//否則才會真正的樹化 -> 剪枝final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();}*/}
}
3.Map 接口實現類-Hashtable
3.1 HashTable 的基本介紹
?擴容【2倍+1】
package com.hspedu.map_;import java.util.Hashtable;@SuppressWarnings({"all"})
public class HashTableExercise {public static void main(String[] args) {Hashtable table = new Hashtable();//oktable.put("john", 100); //ok//table.put(null, 100); //異常 NullPointerException//table.put("john", null);//異常 NullPointerExceptiontable.put("lucy", 100);//oktable.put("lic", 100);//oktable.put("lic", 88);//替換table.put("hello1", 1);table.put("hello2", 1);table.put("hello3", 1);table.put("hello4", 1);table.put("hello5", 1);table.put("hello6", 1);System.out.println(table);//簡單說明一下Hashtable的底層//1. 底層有數組 Hashtable$Entry[] 初始化大小為 11//2. 臨界值 threshold 8 = 11 * 0.75//3. 擴容: 按照自己的擴容機制來進行即可.//4. 執行 方法 addEntry(hash, key, value, index); 添加K-V 封裝到Entry//5. 當 if (count >= threshold) 滿足時,就進行擴容//5. 按照 int newCapacity = (oldCapacity << 1) + 1; 的大小擴容.}
}
3.2?Hashtable 和 HashMap 對比
4.Map 接口實現類-Properties?
4.1基本介紹
4.2?基本使用?
package com.hspedu.map_;import java.util.Properties;/*** @author Linran* @version 1.0*/
@SuppressWarnings({"all"})
public class Properties_ {public static void main(String[] args) {//老韓解讀//1. Properties 繼承 Hashtable//2. 可以通過 k-v 存放數據,當然key 和 value 不能為 null//增加Properties properties = new Properties();//properties.put(null, "abc");//拋出 空指針異常//properties.put("abc", null); //拋出 空指針異常properties.put("john", 100);//k-vproperties.put("lucy", 100);properties.put("lic", 100);properties.put("lic", 88);//如果有相同的key , value被替換System.out.println("properties=" + properties);//通過k 獲取對應值System.out.println(properties.get("lic"));//88//刪除properties.remove("lic");System.out.println("properties=" + properties);//修改properties.put("john", "約翰");System.out.println("properties=" + properties);}
}
?五、總結-開發中如何選擇集合實現類(記住)
?5.1TreeSet源碼解讀
package com.hspedu.set_;import java.util.Comparator;
import java.util.TreeSet;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class TreeSet_ {public static void main(String[] args) {//1. 當我們使用無參構造器,創建TreeSet時,仍然是無序的//2. 老師希望添加的元素,按照字符串大小來排序//3. 使用TreeSet 提供的一個構造器,可以傳入一個比較器(匿名內部類)// 并指定排序規則//4. 簡單看看源碼/*1. 構造器把傳入的比較器對象,賦給了 TreeSet的底層的 TreeMap的屬性this.comparatorpublic TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}2. 在 調用 treeSet.add("tom"), 在底層會執行到if (cpr != null) {//cpr 就是我們的匿名內部類(對象)do {parent = t;//動態綁定到我們的匿名內部類(對象)comparecmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else //如果相等,即返回0,這個Key就沒有加入return t.setValue(value);} while (t != null);}*/// TreeSet treeSet = new TreeSet();TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//下面 調用String的 compareTo方法進行字符串大小比較//如果老韓要求加入的元素,按照長度大小排序//return ((String) o2).compareTo((String) o1);return ((String) o1).length() - ((String) o2).length();}});//添加數據.treeSet.add("jack");treeSet.add("tom");//3treeSet.add("sp");treeSet.add("a");treeSet.add("abc");//3,并不會加入System.out.println("treeSet=" + treeSet);}
}
?5.2 TreeMap源碼解讀
package com.hspedu.map_;import java.util.Comparator;
import java.util.TreeMap;/*** @author 林然* @version 1.0*/
@SuppressWarnings({"all"})
public class TreeMap_ {public static void main(String[] args) {//使用默認的構造器,創建TreeMap, 是無序的(也沒有排序)/*老韓要求:按照傳入的 k(String) 的大小進行排序*/
// TreeMap treeMap = new TreeMap();TreeMap treeMap = new TreeMap(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//按照傳入的 k(String) 的大小進行排序//按照K(String) 的長度大小排序//return ((String) o2).compareTo((String) o1);return ((String) o2).length() - ((String) o1).length();}});treeMap.put("jack", "杰克");treeMap.put("tom", "湯姆");treeMap.put("kristina", "克瑞斯提諾");treeMap.put("smith", "斯密斯");treeMap.put("hsp", "韓順平");//加入不了,會把湯姆修改成韓順平System.out.println("treemap=" + treeMap);/*老韓解讀源碼:1. 構造器. 把傳入的實現了 Comparator接口的匿名內部類(對象),傳給給TreeMap的comparatorpublic TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}2. 調用put方法2.1 第一次添加, 把k-v 封裝到 Entry對象,放入rootEntry<K,V> t = root;if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}2.2 以后添加Comparator<? super K> cpr = comparator;if (cpr != null) {do { //遍歷所有的key , 給當前key找到適當位置parent = t;cmp = cpr.compare(key, t.key);//動態綁定到我們的匿名內部類的compareif (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else //如果遍歷過程中,發現準備添加Key 和當前已有的Key 相等,就不添加return t.setValue(value);} while (t != null);}*/}
}
?六、Collections 工具類
1 Collections 工具類介紹?
2 排序操作:(均為 static 方法)?
package com.hspedu.collections_;import java.util.*;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class Collections_ {public static void main(String[] args) {//創建 ArrayList 集合,用于測試.List list = new ArrayList();list.add("tom");list.add("smith");list.add("king");list.add("milan");list.add("tom");// reverse(List):反轉 List 中元素的順序Collections.reverse(list);System.out.println(list);// shuffle(List):對 List 集合元素進行隨機排序// for (int i = 0; i < 5; i++) {// Collections.shuffle(list);// System.out.println("list=" + list);//sort(List):根據元素的自然順序對指定 List 集合元素按升序排序Collections.sort(list);System.out.println("自然排序后");System.out.println("list=" + list);//按照首字母進行排序// sort(List,Comparator):根據指定的 Comparator 產生的順序對 List 集合元素進行排序
//我們希望按照 字符串的長度大小排序Collections.sort(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {
//可以加入校驗代碼.return ((String) o2).length() - ((String) o1).length();}});System.out.println("字符串長度大小排序=" + list);// swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進行交換
//比如Collections.swap(list, 0, 1);System.out.println("交換后的情況");System.out.println("list=" + list);//Object max(Collection):根據元素的自然順序,返回給定集合中的最大元素System.out.println("自然順序最大元素=" + Collections.max(list));//Object max(Collection,Comparator):根據 Comparator 指定的順序,返回給定集合中的最大元素
//比如,我們要返回長度最大的元素Object maxObject = Collections.max(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {return ((String)o1).length() - ((String)o2).length();}});System.out.println("長度最大的元素=" + maxObject);//Object min(Collection)//Object min(Collection,Comparator)//上面的兩個方法,參考 max 即可//int frequency(Collection,Object):返回指定集合中指定元素的出現次數System.out.println("tom 出現的次數=" + Collections.frequency(list, "tom"));//void copy(List dest,List src):將 src 中的內容復制到 dest 中ArrayList dest = new ArrayList();
//為了完成一個完整拷貝,我們需要先給 dest 賦值,大小和 list.size()一樣for(int i = 0; i < list.size(); i++) {dest.add("");}
//拷貝Collections.copy(dest, list);System.out.println("dest=" + dest);//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對象的所有舊值
//如果 list 中,有 tom 就替換成 湯姆Collections.replaceAll(list, "tom", "湯姆");System.out.println("list 替換后=" + list);}
}
七、本章作業
1.作業一?
package com.hspedu.homework;import java.util.ArrayList;
import java.util.Collections;/*** @author 林然* @version 1.0*/
@SuppressWarnings("all")
public class homework1 {public static void main(String[] args) {News1 new1=new News1("新冠確診病例超千萬,數百萬印度教信徒赴恒河\"圣浴\"引民眾擔憂");News1 new2=new News1("男子突然想起2個月前釣的魚還在網兜里,撈起一看趕緊放生");ArrayList arrayList =new ArrayList();arrayList.add(new1);arrayList.add(new2);Collections.reverse(arrayList);for (Object k:arrayList) {News1 k1 = (News1)k;if(k1.getTitle().length()>=15)System.out.println(k1.getTitle().substring(0, 15) + "...");elseSystem.out.println(k1.getTitle());}}
}
class News1{private String title;private String content;public News1(String title) {this.title = title;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "News{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}
?2.作業二
package com.hspedu.homework;import java.util.ArrayList;
import java.util.Iterator;@SuppressWarnings({"all"})
public class Homework02 {public static void main(String[] args) {ArrayList arrayList = new ArrayList();Car car = new Car("寶馬", 400000);Car car2 = new Car("賓利",5000000);//1.add:添加單個元素arrayList.add(car);arrayList.add(car2);System.out.println(arrayList);//* 2.remove:刪除指定元素arrayList.remove(car);System.out.println(arrayList);//* 3.contains:查找元素是否存在System.out.println(arrayList.contains(car));//F//* 4.size:獲取元素個數System.out.println(arrayList.size());//1//* 5.isEmpty:判斷是否為空System.out.println(arrayList.isEmpty());//F//* 6.clear:清空//System.out.println(arrayList.clear(););//* 7.addAll:添加多個元素System.out.println(arrayList);arrayList.addAll(arrayList);//2個賓利System.out.println(arrayList);//* 8.containsAll:查找多個元素是否都存在arrayList.containsAll(arrayList);//T//* 9.removeAll:刪除多個元素//arrayList.removeAll(arrayList); //相當于清空//* 使用增強for和 迭代器來遍歷所有的car , 需要重寫 Car 的toString方法for (Object o : arrayList) {System.out.println(o);//}System.out.println("===迭代器===");Iterator iterator = arrayList.iterator();while (iterator.hasNext()) {Object next = iterator.next();System.out.println(next);}}
}
/*** 使用ArrayList 完成對 對象 Car {name, price} 的各種操作* 1.add:添加單個元素* 2.remove:刪除指定元素* 3.contains:查找元素是否存在* 4.size:獲取元素個數* 5.isEmpty:判斷是否為空* 6.clear:清空* 7.addAll:添加多個元素* 8.containsAll:查找多個元素是否都存在* 9.removeAll:刪除多個元素* 使用增強for和 迭代器來遍歷所有的car , 需要重寫 Car 的toString方法*/
class Car {private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}
?3.作業三
package com.hspedu.homework;import java.util.*;/*** @author 林然* @version 1.0*/
public class homework3 {@SuppressWarnings("all")public static void main(String[] args) {Map m = new HashMap();m.put("jack",650);m.put("tom",1200);m.put("smith",2900);m.replace("jack",2600);Set keys =m.keySet();//更新工資for(Object k :keys){ int salary=(int)(m.get(k));m.replace(k,salary+100);}//遍歷集合中的員工//遍歷 EntrySetSet entrySet = m.entrySet();//迭代器Iterator iterator = entrySet.iterator();while (iterator.hasNext()) {Map.Entry entry = (Map.Entry)iterator.next();System.out.println(entry.getKey() + "-" + entry.getValue());}System.out.println("====遍歷所有的工資====");Collection values = m.values();for (Object value : values) {System.out.println("工資=" + value);}}
}
?4.作業四
5.作業五?
//package com.hspedu.homework;
//
//import java.util.TreeSet;
////@SuppressWarnings({"all"})
//public class Homework05 {
// public static void main(String[] args) {
// TreeSet treeSet = new TreeSet();
// //分析源碼
// //add 方法,因為 TreeSet() 構造器沒有傳入Comparator接口的匿名內部類
// //所以在底層 Comparable<? super K> k = (Comparable<? super K>) key;
// //即 把 Perosn轉成 Comparable類型
// treeSet.add(new Person());//ClassCastException.
// treeSet.add(new Person());//ClassCastException.
// treeSet.add(new Person());//ClassCastException.
// treeSet.add(new Person());//ClassCastException.
// treeSet.add(new Person());//ClassCastException.
//
// System.out.println(treeSet);
//
// }
//}
//
//class Person implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
//}
?6.作業六
【只要id和name不一樣,那么我們認為他們不是同一個對象】
【remove中是利用1001和CC來計算哈希值,也就是他沒辦法找到p1所在的位置【1001+AA】】
package com.hspedu.homework;import java.util.HashSet;
import java.util.Objects;@SuppressWarnings({"all"})
public class Homework06 {public static void main(String[] args) {HashSet set = new HashSet();//okPerson p1 = new Person(1001,"AA");//okPerson p2 = new Person(1002,"BB");//okset.add(p1);//okset.add(p2);//okp1.name = "CC";set.remove(p1);System.out.println(set);//2set.add(new Person(1001,"CC"));System.out.println(set);//3set.add(new Person(1001,"AA"));System.out.println(set);//4}
}class Person {public String name;public int id;public Person(int id, String name) {this.name = name;this.id = id;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return id == person.id &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, id);}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", id=" + id +'}';}
}