三國手游源碼(手游源碼搭建教程)

集合的理解和好處

前面我們保存多個數(shù)據(jù)使用的是數(shù)組,那么數(shù)組有不足的地方,我們分析一下

數(shù)組

有的玩家喜歡游戲中角色的各式皮膚,有的玩家吐槽游戲匹配機(jī)制,可謂是幾家歡喜幾家愁。因此,有的人可能就會想到:與其打王者,不如自己開發(fā)王者。

List 接口是 Collection接口的子接口

醫(yī)療健康、在線教育、企服、大文娛等利好

List 接口的常用方法

打標(biāo)簽:比如微信收藏功能,你可以為自己收藏的每一篇文章打標(biāo)簽,這樣你可以快速的找到被添加了某個標(biāo)簽的所有文章。

    模擬HashMap觸發(fā)擴(kuò)容、樹化情況,并Debug 驗證.

    private UserDao userDao; //利用set進(jìn)行動態(tài)實現(xiàn)值的注入! public void setUserDao(UserDao userDao) { this.userDao = userDao; } ========================================= public static void main(String[] args) { //用戶實際調(diào)用的是業(yè)務(wù)層,dao層它們不需要接觸! UserService userService = new UserServiceImpl(); ((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl()); userService.getUser(); }

    mysql數(shù)據(jù)庫

    注解 不是自己的類使用不了,維護(hù)相對復(fù)雜!

    List集合中的每個元素都有其對應(yīng)的順序索引,即支持索引。

    在一個項目中,根據(jù)業(yè)務(wù)靈活選擇,也可能這樣,一個模塊使用的是ArrayList,另外一個模塊是LinkedList,也就是說,要根據(jù)業(yè)務(wù)來進(jìn)行選擇。

    張三

    VAR3:=LLV(LOW,34);

    @Component @Scope("prototype") public class User { public String name; //相當(dāng)于 @Value("kuangshen") public void setName(String name) { this.name = name; } }

    VAR5:=CROSS(短趨勢,長趨勢)AND 長趨勢<25;

    Person[] pers = new Person[1]; //大小是1 per[0] = new Person(); //增加新的Person對象? Person[] pers2 = new Person[pers.length+1];//新創(chuàng)建數(shù)組 for(){} //拷貝pers數(shù)組的元素到per2 pers2[pers2.length-1] = new Person()://添加新的對象 復(fù)制代碼集合

    package com.hspedu.collection_; import java.util.ArrayList; import java.util.List; public class CollectionMethod { @SuppressWarnings({"all"}) public static void main(String[] args) { List list = new ArrayList(); // add:添加單個元素 list.add("jack"); list.add(10);//list.add(new Integer(10)) 本質(zhì)是對象 list.add(true); System.out.println("list=" + list); // remove:刪除指定元素 list.remove(0);//刪除第一個元素 返回boolen list.remove(true);//指定刪除某個元素 返回該obj System.out.println("list=" + list); // contains:查找元素是否存在 System.out.println(list.contains("jack"));//T // size:獲取元素個數(shù) 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("三國演義"); list.addAll(list2); System.out.println("list=" + list); // containsAll:查找多個元素是否都存在 System.out.println(list.containsAll(list2));//T // removeAll:刪除多個元素 list.add("聊齋"); list2.add("時間是金"); list.removeAll(list2); System.out.println("list=" + list);//[聊齋] // 說明:以ArrayList實現(xiàn)類來演示. } } 復(fù)制代碼Collection 接口遍歷元素方式1-使用Iterator

      lterator iterator = coll.iterator(); //得到一個集合的迭代器 //hasNext():判斷是否還有下一個元素 while(iterator.hasNext()){ //next()作用:1.下移2.將下移以后集合位置上的元素返回 System.out.println(iterator.next()); } 復(fù)制代碼

      package com.hspedu.collection_; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class CollectionIterator { @SuppressWarnings({"all"}) public static void main(String[] args) { Collection col = new ArrayList(); col.add(new Book("三國演義", "羅貫中", 10.1)); col.add(new Book("小李飛刀", "古龍", 5.1)); col.add(new Book("紅樓夢", "曹雪芹", 34.6)); //System.out.println("col=" + col); //現(xiàn)在老師希望能夠遍歷 col集合 //1. 先得到 col 對應(yīng)的 迭代器 Iterator iterator = col.iterator(); //2. 使用while循環(huán)遍歷 // while (iterator.hasNext()) {//判斷是否還有數(shù)據(jù) // //返回下一個元素,類型是Object // Object obj = iterator.next(); // System.out.println("obj=" + obj); // } //教大家一個快捷鍵,快速生成 while => itit //顯示所有的快捷鍵的的快捷鍵 ctrl + j while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println("obj=" + obj); } //3. 當(dāng)退出while循環(huán)后 , 這時iterator迭代器,指向最后的元素 // iterator.next();// 此時如果再取則會報錯 NoSuchElementException //4. 如果希望再次遍歷,需要重置我們的迭代器 iterator = col.iterator(); // 重置迭代器 System.out.println("===第二次遍歷==="); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println("obj=" + obj); } } } 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; } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", author='" + author + '\'' + ", price=" + price + '}'; } } 復(fù)制代碼Collection 接口遍歷對象方式2-for 循環(huán)增強(qiáng)

      package com.hspedu.collection_; import java.util.ArrayList; import java.util.Collection; public class CollectionFor { @SuppressWarnings({"all"}) public static void main(String[] args) { Collection col = new ArrayList(); col.add(new Book("三國演義", "羅貫中", 10.1)); col.add(new Book("小李飛刀", "古龍", 5.1)); col.add(new Book("紅樓夢", "曹雪芹", 34.6)); //1. 使用增強(qiáng)for, 在Collection集合 //2. 增強(qiáng)for, 底層仍然是迭代器 //3. 增強(qiáng)for可以理解成就是簡化版本的 迭代器遍歷 //4. 快捷鍵方式 I // for (Object book : col) { // System.out.println("book=" + book); // } for (Object o : col) { System.out.println("book=" + o); } //增強(qiáng)for,也可以直接在數(shù)組使用 // int[] nums = {1, 8, 10, 90}; // for (int i : nums) { // System.out.println("i=" + i); // } } } 復(fù)制代碼List 接口和常用方法List 接口基本介紹

      package com.hspedu.list_; import java.util.ArrayList; import java.util.List; 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的位置插入一個對象(index 從0開始) list.add(1, "韓順平"); System.out.println("list=" + list); // boolean addAll(int index, Collection eles):從index位置開始將eles中的所有元素添加進(jìn)來 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在集合中首次出現(xiàn)的位置 System.out.println(list.indexOf("tom"));//2 // int lastIndexOf(Object obj):返回obj在當(dāng)前集合中末次出現(xiàn)的位置 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):設(shè)置指定index位置的元素為ele , 相當(dāng)于是替換. list.set(1, "瑪麗"); System.out.println("list=" + list); // List subList(int fromIndex, int toIndex):返回從fromIndex到toIndex位置的子集合 // 注意返回的子集合 fromIndex <= subList < toIndex List returnlist = list.subList(0, 2); System.out.println("returnlist=" + returnlist); } } 復(fù)制代碼List 接口課堂練習(xí)

      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的實現(xiàn)類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); } } } 復(fù)制代碼List 的三種遍歷方式[ArrayList, LinkedList,Vector]

      package com.hspedu.list_; import java.util.*; public class ListFor { @SuppressWarnings({"all"}) public static void main(String[] args) { //List 接口的實現(xiàn)子類 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("=====增強(qiáng)for====="); //2. 增強(qiáng)for for (Object o : list) { System.out.println("o=" + o); } System.out.println("=====普通for===="); //3. 使用普通for for (int i = 0; i < list.size(); i++) { System.out.println("對象=" + list.get(i)); } } } 復(fù)制代碼實現(xiàn)類的課堂練習(xí)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)); //如何對集合進(jìn)行排序 //遍歷 for (Object o : list) { System.out.println(o); } //冒泡排序 sort(list); System.out.println("==排序后=="); for (Object o : list) { System.out.println(o); } } //靜態(tài)方法 //價格要求是從小到大 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++) { //取出對象Book Book 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); } } } } } 復(fù)制代碼ArrayList 底層結(jié)構(gòu)和源碼分析ArrayList 的注意事項

        當(dāng)創(chuàng)建ArrayList對象時,如果使用的是無參構(gòu)造器,則初始elementData容量為0,第1次添加,則擴(kuò)容elementData為10,如需要再次擴(kuò)容,則擴(kuò)容elementData為1.5倍

        如果使用的是指定大小的構(gòu)造器,則初始elementData容量為指定大小,如果需要擴(kuò)容,則直接擴(kuò)容elementData為1.5倍

        package com.hspedu.list_; import java.util.Vector; @SuppressWarnings({"all"}) public class Vector_ { public static void main(String[] args) { //無參構(gòu)造器 //有參數(shù)的構(gòu)造 Vector vector = new Vector(8); for (int i = 0; i < 10; i++) { vector.add(i); } vector.add(100); System.out.println("vector=" + vector); //1. new Vector() 底層 /* public Vector() { this(10); } 補(bǔ)充:如果是 Vector vector = new Vector(8); 走的方法: public Vector(int initialCapacity) { this(initialCapacity, 0); } 2. vector.add(i) 2.1 //下面這個方法就添加數(shù)據(jù)到vector集合 public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } 2.2 //確定是否需要擴(kuò)容 條件 : minCapacity - elementData.length>0 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } 2.3 //如果 需要的數(shù)組大小 不夠用,就擴(kuò)容 , 擴(kuò)容的算法 //newCapacity = oldCapacity + ((capacityIncrement > 0) ? // capacityIncrement : oldCapacity); //就是擴(kuò)容兩倍. private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } */ } } 復(fù)制代碼Vector 和 ArrayList 的比較LinkedList 底層結(jié)構(gòu)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("老韓"); //連接三個結(jié)點,形成雙向鏈表 //jack -> tom -> hsp jack.next = tom; tom.next = hsp; //hsp -> tom -> jack hsp.pre = tom; tom.pre = jack; Node first = jack;//讓first引用指向jack,就是雙向鏈表的頭結(jié)點 Node last = hsp; //讓last引用指向hsp,就是雙向鏈表的尾結(jié)點 //演示,從頭到尾進(jìn)行遍歷 System.out.println("===從頭到尾進(jìn)行遍歷==="); 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; } //演示鏈表的添加對象/數(shù)據(jù),是多么的方便 //要求,是在 tom --------- 插入一個對象 smith //1. 先創(chuàng)建一個 Node 結(jié)點,name 就是 smith Node smith = new Node("smith"); //下面就把 smith 加入到雙向鏈表了 smith.next = hsp; smith.pre = tom; hsp.pre = smith; tom.next = smith; //讓first 再次指向jack first = jack;//讓first引用指向jack,就是雙向鏈表的頭結(jié)點 System.out.println("===從頭到尾進(jìn)行遍歷==="); while (true) { if(first == null) { break; } //輸出first 信息 System.out.println(first); first = first.next; } last = hsp; //讓last 重新指向最后一個結(jié)點 //演示,從尾到頭的遍歷 System.out.println("====從尾到頭的遍歷===="); while (true) { if(last == null) { break; } //輸出last 信息 System.out.println(last); last = last.pre; } } } //定義一個Node 類,Node 對象 表示雙向鏈表的一個結(jié)點 class Node { public Object item; //真正存放數(shù)據(jù) public Node next; //指向后一個結(jié)點 public Node pre; //指向前一個結(jié)點 public Node(Object name) { this.item = name; } public String toString() { return "Node name=" + item; } }LinkedList 的增刪改查案例

          package com.hspedu.list_; import java.util.Iterator; import java.util.LinkedList; @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); //演示一個刪除結(jié)點的 linkedList.remove(); // 這里默認(rèn)刪除的是第一個結(jié)點 //linkedList.remove(2); System.out.println("linkedList=" + linkedList); //修改某個結(jié)點對象 linkedList.set(1, 999); System.out.println("linkedList=" + linkedList); //得到某個結(jié)點對象 //get(1) 是得到雙向鏈表的第二個對象 Object o = linkedList.get(1); System.out.println(o);//999 //因為LinkedList 是 實現(xiàn)了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遍歷增強(qiáng)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 = null 3. 執(zhí)行 添加 public boolean add(E e) { linkLast(e); return true; } 4.將新的結(jié)點,加入到雙向鏈表的最后 void linkLast(E e) { final Node l = last; final Node newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } */ /* 讀源碼 linkedList.remove(); // 這里默認(rèn)刪除的是第一個結(jié)點 1. 執(zhí)行 removeFirst public E remove() { return removeFirst(); } 2. 執(zhí)行 public E removeFirst() { final Node f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } 3. 執(zhí)行 unlinkFirst, 將 f 指向的雙向鏈表的第一個結(jié)點拿掉 private E unlinkFirst(Node f) { // assert f == first && f != null; final E element = f.item; final Node next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; } */ } }ArrayList 和LinkedList 比較ArrayList 和LinkedList 的比較

          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 接口的實現(xiàn)類 HashSet 來講解Set 接口的方法 //2. set 接口的實現(xiàn)類的對象(Set接口對象), 不能存放重復(fù)的元素, 可以添加一個null //3. set 接口對象存放數(shù)據(jù)是無序(即添加的順序和取出的順序不一致) //4. 注意:取出的順序的順序雖然不是添加的順序,但是他的固定. Set set = new HashSet(); set.add("john"); set.add("lucy"); set.add("john");//重復(fù) 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: 增強(qiáng)for System.out.println("=====增強(qiáng)for===="); for (Object o : set) { System.out.println("o=" + o); } //set 接口對象,不能通過索引來獲取 } }Set 接口實現(xiàn)類-HashSetHashSet 的全面說明

            package com.hspedu.set_; import java.util.HashSet; import java.util.Set; @SuppressWarnings({"all"}) public class HashSet_ { public static void main(String[] args) { //1. 構(gòu)造器走的源碼 /* public HashSet() { map = new HashMap<>(); } 2. HashSet 可以存放null ,但是只能有一個null,即元素不能重復(fù) */ Set hashSet = new HashSet(); hashSet.add(null); hashSet.add(null); System.out.println("hashSet=" + hashSet); } }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. 在執(zhí)行add方法后,會返回一個boolean值 //2. 如果添加成功,返回 true, 否則返回false //3. 可以通過 remove 指定刪除哪個對象 System.out.println(set.add("john"));//T System.out.println(set.add("lucy"));//T System.out.println(set.add("john"));//F System.out.println(set.add("jack"));//T System.out.println(set.add("Rose"));//T set.remove("john"); System.out.println("set=" + set);//3個 // set = new HashSet(); System.out.println("set=" + set);//0 //4 Hashset 不能添加相同的元素/數(shù)據(jù)? set.add("lucy");//添加成功 set.add("lucy");//加入不了 set.add(new Dog("tom"));//OK 不同的對象 set.add(new Dog("tom"));//Ok System.out.println("set=" + set); //在加深一下. 非常經(jīng)典的面試題. //看源碼,做分析, 先給小伙伴留一個坑,以后講完源碼,你就了然 //去看他的源碼,即 add 到底發(fā)生了什么? => 底層機(jī)制. set.add(new String("hsp"));//ok set.add(new String("hsp"));//加入不了. System.out.println("set=" + set); } } class Dog { //定義了Dog類 private String name; public Dog(String name) { this.name = name; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + '}'; } }HashSet 底層機(jī)制說明

            package com.hspedu.set_; @SuppressWarnings({"all"}) public class HashSetStructure { public static void main(String[] args) { //模擬一個HashSet的底層 (HashMap 的底層結(jié)構(gòu)) //1. 創(chuàng)建一個數(shù)組,數(shù)組的類型是 Node[] //2. 有些人,直接把 Node[] 數(shù)組稱為 表 Node[] table = new Node[16]; //3. 創(chuàng)建結(jié)點 Node john = new Node("john", null); table[2] = john; Node jack = new Node("jack", null); john.next = jack;// 將jack 結(jié)點掛載到j(luò)ohn Node rose = new Node("Rose", null); jack.next = rose;// 將rose 結(jié)點掛載到j(luò)ack Node lucy = new Node("lucy", null); table[3] = lucy; // 把lucy 放到 table表的索引為3的位置. System.out.println("table=" + table); } } class Node { //結(jié)點, 存儲數(shù)據(jù), 可以指向下一個結(jié)點,從而形成鏈表 Object item; //存放數(shù)據(jù) Node next; // 指向下一個結(jié)點 public Node(Object item, Node next) { this.item = item; this.next = next; } }

            package com.hspedu.set_; import java.util.HashSet; @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. 執(zhí)行 HashSet() public HashSet() { map = new HashMap<>(); } 2. 執(zhí)行 add() public boolean add(E e) {//e = "java" return map.put(e, PRESENT)==null;// (static) PRESENT = new Object(); } 3.執(zhí)行 put() , 該方法會執(zhí)行 hash(key) 得到key對應(yīng)的hash值 算法:h = key.hashCode()) ^ (h >>> 16) 可見這個hash的值并不是hashcode,而是做了一定的處理 >>> 16. public V put(K key, V value) {//key = "java" value = PRESENT 共享 return putVal(hash(key), key, value, false, true); } 4.執(zhí)行 putVal !!!!!!!!!!!!!!!!! final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node[] tab; Node p; int n, i; //定義了輔助變量 //table 就是 HashMap 的一個數(shù)組,類型是 Node[] (前面我們也模擬過) //if 語句表示如果當(dāng)前table 是null, 或者 大小=0 //就是第一次擴(kuò)容,到16個空間. if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; //(1)根據(jù)key,得到hash 去計算該key應(yīng)該存放到table表的哪個索引位置并把這個位置的對象,賦給 p //(2)判斷 p 是否為null //(2.1) 如果 p 為null, 表示還沒有存放元素, 就創(chuàng)建一個 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); // 這個null類似與模擬節(jié)點的null,其后面還沒有掛載節(jié)點 else { //一個開發(fā)技巧提示: 在需要局部變量(輔助變量)時候,在創(chuàng)建 Node e; K k; // //如果當(dāng)前索引位置對應(yīng)的鏈表的第一個元素和準(zhǔn)備添加的key的hash值一樣 //并且滿足 下面兩個條件之一: // (1) 準(zhǔn)備加入的key p 指向的Node 結(jié)點的 key 是同一個對象 // (2) p 指向的Node 結(jié)點的 key 的equals() 和準(zhǔn)備加入的key比較后相同 //就不能加入 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; //再判斷 p 是不是一顆紅黑樹, //如果是一顆紅黑樹,就調(diào)用 putTreeVal , 來進(jìn)行添加 else if (p instanceof TreeNode) e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value); else {//如果table對應(yīng)索引位置,已經(jīng)是一個鏈表, 就使用for循環(huán)比較 //(1) 依次和該鏈表的每一個元素比較后,都不相同, 則加入到該鏈表的最后 // 注意在把元素添加到鏈表后,立即判斷 該鏈表是否已經(jīng)達(dá)到8個結(jié)點 // , 就調(diào)用 treeifyBin() 對當(dāng)前這個鏈表進(jìn)行樹化(轉(zhuǎn)成紅黑樹) // 注意,在轉(zhuǎn)成紅黑樹時,要進(jìn)行判斷, 判斷條件 // if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY(64)) // resize(); // 如果上面條件成立,先table擴(kuò)容. // 只有上面條件不成立時,才進(jìn)行轉(zhuǎn)成紅黑樹 //(2) 依次和該鏈表的每一個元素比較過程中,如果有相同情況,就直接break for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD(8) - 1) // -1 for 1st treeifyBin(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 key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; //size 就是我們每加入一個結(jié)點Node(k,v,h,next), size++ if (++size > threshold) resize();//擴(kuò)容 afterNodeInsertion(evict); return null; } */ } }

              HashSet底層是HashMap,第一次添加時,table數(shù)組擴(kuò)容到16,臨界值(threshold)是16* 加載因子 (loadFactor)是0.75 = 12

              如果table數(shù)組使用到了臨界值12,就會擴(kuò)容到16* 2=32,新的臨界值就是32*0.75 =24.依次類推

              package com.hspedu.set_; import java.util.HashSet; import java.util.Objects; @SuppressWarnings({"all"}) public class HashSetIncrement { public static void main(String[] args) { /* HashSet底層是HashMap, 第一次添加時,table 數(shù)組擴(kuò)容到 16, 臨界值(threshold)是 16*加載因子(loadFactor)是0.75 = 12 如果table 數(shù)組使用到了臨界值 12,就會擴(kuò)容到 16 * 2 = 32, 新的臨界值就是 32*0.75 = 24, 依次類推 */ HashSet hashSet = new HashSet(); // for(int i = 1; i <= 100; i++) { // hashSet.add(i);//1,2,3,4,5...100 // } /* 在Java8中, 如果一條鏈表的元素個數(shù)到達(dá) TREEIFY_THRESHOLD(默認(rèn)是 8 ), 并且table的大小 >= MIN_TREEIFY_CAPACITY(默認(rèn)64),就會進(jìn)行樹化(紅黑樹), 否則仍然采用數(shù)組擴(kuò)容機(jī)制 */ // for(int i = 1; i <= 12; i++) { // hashSet.add(new A(i));// // } /* 當(dāng)我們向hashset增加一個元素,-> Node -> 加入table , 就算是增加了一個size++ */ for(int i = 1; i <= 7; i++) {//在table的某一條鏈表上添加了 7個A對象 hashSet.add(new A(i));// } for(int i = 1; i <= 7; i++) {//在table的另外一條鏈表上添加了 7個B對象 hashSet.add(new B(i));// } } } class B { private int n; public B(int n) { this.n = n; } @Override public int hashCode() { return 200; } } class A { private int n; public A(int n) { this.n = n; } @Override public int hashCode() { return 100; } }HashSet 課堂練習(xí)1

              1.創(chuàng)建3個Employee對象放入 HashSet中

              2.當(dāng)name和age的值相同時,認(rèn)為是相同員工,不能添加到HashSet集合中

              package com.hspedu.set_; import java.util.LinkedHashSet; import java.util.Set; @SuppressWarnings({"all"}) public class LinkedHashSetSource { public static void main(String[] args) { //分析一下LinkedHashSet的底層機(jī)制 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 加入順序和取出元素/數(shù)據(jù)的順序一致 //2. LinkedHashSet 底層維護(hù)的是一個LinkedHashMap(是HashMap的子類) //3. LinkedHashSet 底層結(jié)構(gòu) (數(shù)組table+雙向鏈表) //4. 添加第一次時,直接將 數(shù)組table 擴(kuò)容到 16 ,存放的結(jié)點類型是 LinkedHashMap$Entry //5. 數(shù)組是 HashMap$Node[] 存放的元素/數(shù)據(jù)是 LinkedHashMap$Entry類型 /* //繼承關(guān)系是在內(nèi)部類完成. static class Entry extends HashMap.Node { Entry before, after; Entry(int hash, K key, V value, Node 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; } }

              package com.hspedu.map_; import java.util.HashMap; import java.util.Map; @SuppressWarnings({"all"}) public class Map_ { public static void main(String[] args) { //Map 接口實現(xiàn)類的特點, 使用實現(xiàn)類HashMap //1. Map與Collection并列存在。用于保存具有映射關(guān)系的數(shù)據(jù):Key-Value(雙列元素) //2. Map 中的 key 和 value 可以是任何引用類型的數(shù)據(jù),會封裝到HashMap$Node 對象中 //3. Map 中的 key 不允許重復(fù),原因和HashSet 一樣,前面分析過源碼. //4. Map 中的 value 可以重復(fù) //5. Map 的key 可以為 null, value 也可以為null ,注意 key 為null, // 只能有一個,value 為null ,可以多個 //6. 常用String類作為Map的 key //7. key 和 value 之間存在單向一對一關(guān)系,即通過指定的 key 總能找到對應(yīng)的 value Map map = new HashMap(); map.put("no1", "韓順平");//k-v map.put("no2", "張無忌");//k-v map.put("no1", "張三豐");//當(dāng)有相同的k , 就等價于替換. map.put("no3", "張三豐");//k-v map.put(null, null); //k-v map.put(null, "abc"); //等價替換 map.put("no4", null); //k-v map.put("no5", null); //k-v map.put(1, "趙敏");//k-v map.put(new Object(), "金毛獅王");//k-v // 通過get 方法,傳入 key ,會返回對應(yīng)的value System.out.println(map.get("no2"));//張無忌 System.out.println("map=" + 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-v map.put("no2", "張無忌");//k-v map.put(new Car(), new Person());//k-v //老韓解讀 //1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null) //2. k-v 為了方便程序員的遍歷,還會 創(chuàng)建 EntrySet 集合 ,該集合存放的元素的類型 Entry, 而一個Entry // 對象就有k,v EntrySet> 即: transient Set> entrySet; //3. entrySet 中, 定義的類型是 Map.Entry ,但是實際上存放的還是 HashMap$Node // 這時因為 static class Node implements Map.Entry //4. 當(dāng)把 HashMap$Node 對象 存放到 entrySet 就方便我們的遍歷, 因為 Map.Entry 提供了重要方法 // K getKey(); V getValue(); Set set = map.entrySet(); System.out.println(set.getClass());// HashMap$EntrySet for (Object obj : set) { //System.out.println(obj.getClass()); //HashMap$Node //為了從 HashMap$Node 取出k-v //1. 先做一個向下轉(zhuǎn)型 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{ }Map 接口常用方法

                package com.hspedu.map_; import java.util.*; @SuppressWarnings({"all"}) public class MapFor { public static void main(String[] args) { Map map = new HashMap(); map.put("鄧超", "孫儷"); map.put("王寶強(qiáng)", "馬蓉"); map.put("宋喆", "馬蓉"); map.put("劉令博", null); map.put(null, "劉亦菲"); map.put("鹿晗", "關(guān)曉彤"); //第一組: 先取出 所有的Key , 通過Key 取出對應(yīng)的Value Set keyset = map.keySet(); //(1) 增強(qiáng)for System.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) 增強(qiáng)for System.out.println("---取出所有的value 增強(qiáng)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-v Set entrySet = map.entrySet();// EntrySet> //(1) 增強(qiáng)for System.out.println("----使用EntrySet 的 for增強(qiáng)(第3種)----"); for (Object entry : entrySet) { //將entry 轉(zhuǎn)成 Map.Entry Map.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 -實現(xiàn)-> Map.Entry (getKey,getValue) //向下轉(zhuǎn)型 Map.Entry Map.Entry m = (Map.Entry) entry; System.out.println(m.getKey() + "-" + m.getValue()); } } }Map 接口課堂練習(xí)

                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 -> 增強(qiáng)for Set keySet = hashMap.keySet(); System.out.println("====第一種遍歷方式===="); for (Object key : keySet) { //先獲取value Emp 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()) { // 真正的運行類型是Node,可以getClass看一下 Map.Entry entry = (Map.Entry)iterator.next(); //通過entry 取得key 和 value Emp 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; } @Override public String toString() { return "Emp{" + "name='" + name + '\'' + ", sal=" + sal + ", id=" + id + '}'; } }Map 接口實現(xiàn)類-HashMapHashMap 小結(jié)

                  當(dāng)創(chuàng)建對象時,將加載因子(Ioadfactor)初始化為0.75.

                  第1次添加,則需要擴(kuò)容table容量為16,臨界值(threshold)為12 (16*0.75)

                  以后再擴(kuò)容,則需要擴(kuò)容table容量為原來的2倍(32),臨界值為原來的2倍,即24,依次類推.

                  package com.hspedu.map_; import java.util.Hashtable; @SuppressWarnings({"all"}) public class HashTableExercise { public static void main(String[] args) { Hashtable table = new Hashtable();//ok table.put("john", 100); //ok //table.put(null, 100); //異常 NullPointerException //table.put("john", null);//異常 NullPointerException table.put("lucy", 100);//ok table.put("lic", 100);//ok table.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. 底層有數(shù)組 Hashtable$Entry[] 初始化大小為 11 //2. 臨界值 threshold 8 = 11 * 0.75 //3. 擴(kuò)容: //4. 執(zhí)行 方法 addEntry(hash, key, value, index); 添加K-V 封裝到Entry //5. 當(dāng) if (count >= threshold) 滿足時,就進(jìn)行擴(kuò)容 //5. 按照 int newCapacity = (oldCapacity << 1) + 1; 的大小擴(kuò)容. 兩倍加一 } }Hashtable 和HashMap 對比Map 接口實現(xiàn)類-Properties基本介紹

                    說明:工作后 xxx.properties文件通常作為配置文件,這個知識點在IO流舉例,有興趣可先看文章。cnblogs.com/xudong-bupt/p/3758136.html

                    package com.hspedu.map_; import java.util.Properties; @SuppressWarnings({"all"}) public class Properties_ { public static void main(String[] args) { //1. Properties 繼承 Hashtable //2. 可以通過 k-v 存放數(shù)據(jù),當(dāng)然key 和 value 不能為 null //增加 Properties properties = new Properties(); //properties.put(null, "abc");//拋出 空指針異常 //properties.put("abc", null); //拋出 空指針異常 properties.put("john", 100);//k-v properties.put("lucy", 100); properties.put("lic", 100); properties.put("lic", 88);//如果有相同的key , value被替換 System.out.println("properties=" + properties); //通過k 獲取對應(yīng)值 System.out.println(properties.get("lic"));//88 System.out.println(properties.getProperty("lic")); //刪除 properties.remove("lic"); System.out.println("properties=" + properties); //修改 properties.put("john", "約翰"); System.out.println("properties=" + properties); } } 復(fù)制代碼總結(jié)-開發(fā)中如何選擇集合實現(xiàn)類!

                    package com.hspedu.set_; import java.util.Comparator; import java.util.TreeSet; @SuppressWarnings({"all"}) public class TreeSet_ { public static void main(String[] args) { //1. 當(dāng)我們使用無參構(gòu)造器,創(chuàng)建TreeSet時,仍然是無序的 //2. 希望添加的元素,按照字符串大小來排序 //3. 使用TreeSet 提供的一個構(gòu)造器,可以傳入一個比較器(匿名內(nèi)部類)并指定排序規(guī)則 //4. 簡單看看源碼 /* 1. 構(gòu)造器把傳入的比較器對象,賦給了 TreeSet的底層的 TreeMap 的屬性 this.comparator public TreeMap(Comparator comparator) { this.comparator = comparator; } 2. 在 調(diào)用 treeSet.add("tom"), 在底層會執(zhí)行到 if (cpr != null) {//cpr 就是我們的匿名內(nèi)部類(對象) do { parent = t; //動態(tài)綁定到我們的匿名內(nèi)部類(對象)compare cmp = 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() { @Override public int compare(Object o1, Object o2) { //下面 調(diào)用String的 compareTo方法進(jìn)行字符串大小比較 //return ((String) o2).compareTo((String) o1); //如果要求加入的元素,按照長度大小排序 return ((String) o1).length() - ((String) o2).length(); } }); //添加數(shù)據(jù). treeSet.add("jack"); treeSet.add("tom");// 3 treeSet.add("sp"); treeSet.add("a"); treeSet.add("abc");// 長度為3,加不進(jìn)去 System.out.println("treeSet=" + treeSet); } }TreeMap

                    package com.hspedu.map_; import java.util.Comparator; import java.util.TreeMap; @SuppressWarnings({"all"}) public class TreeMap_ { public static void main(String[] args) { //使用默認(rèn)的構(gòu)造器,創(chuàng)建TreeMap, 是無序的(也沒有排序) /* 要求:按照傳入的 k(String) 的大小進(jìn)行排序 */ // TreeMap treeMap = new TreeMap(); TreeMap treeMap = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { //按照傳入的 k(String) 的大小進(jìn)行排序 //按照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. 構(gòu)造器. 把傳入的實現(xiàn)了 Comparator接口的匿名內(nèi)部類(對象),傳給給TreeMap的comparator public TreeMap(Comparator comparator) { this.comparator = comparator; } 2. 調(diào)用put方法 2.1 第一次添加, 把k-v 封裝到 Entry對象,放入root Entry t = root; if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; } 2.2 以后添加 Comparator cpr = comparator; if (cpr != null) { do { //遍歷所有的key , 給當(dāng)前key找到適當(dāng)位置 parent = t; cmp = cpr.compare(key, t.key);//動態(tài)綁定到我們的匿名內(nèi)部類的compare if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else //如果遍歷過程中,發(fā)現(xiàn)準(zhǔn)備添加Key 和當(dāng)前已有的Key 相等,就不添加 return t.setValue(value); } while (t != null); } */ } }Collections 工具類Collections 工具類介紹

                      package com.hspedu.collections_; import java.util.*; @SuppressWarnings({"all"}) public class Collections_ { public static void main(String[] args) { //創(chuàng)建ArrayList 集合,用于測試. List list = new ArrayList(); list.add("tom"); list.add("smith"); list.add("king"); list.add("milan"); list.add("tom"); // reverse(List):反轉(zhuǎn) List 中元素的順序 Collections.reverse(list); System.out.println("list=" + list); // shuffle(List):對 List 集合元素進(jìn)行隨機(jī)排序 // for (int i = 0; i < 5; i++) { // Collections.shuffle(list); // System.out.println("list=" + list); // } // sort(List):根據(jù)元素的自然順序?qū)χ付?List 集合元素按升序排序 Collections.sort(list); System.out.println("自然排序后"); System.out.println("list=" + list); // sort(List,Comparator):根據(jù)指定的 Comparator 產(chǎn)生的順序?qū)?List 集合元素進(jìn)行排序 //我們希望按照 字符串的長度大小排序 Collections.sort(list, new Comparator() { @Override public int compare(Object o1, Object o2) { //可以加入校驗代碼. return ((String) o2).length() - ((String) o1).length(); } }); System.out.println("字符串長度大小排序=" + list); // swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進(jìn)行交換 //比如 Collections.swap(list, 0, 1); System.out.println("交換后的情況"); System.out.println("list=" + list); //Object max(Collection):根據(jù)元素的自然順序,返回給定集合中的最大元素 System.out.println("自然順序最大元素=" + Collections.max(list)); //Object max(Collection,Comparator):根據(jù) Comparator 指定的順序,返回給定集合中的最大元素 //比如,我們要返回長度最大的元素 Object maxObject = Collections.max(list, new Comparator() { @Override public 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):返回指定集合中指定元素的出現(xiàn)次數(shù) System.out.println("tom出現(xiàn)的次數(shù)=" + Collections.frequency(list, "tom")); //void copy(List dest,List src):將src中的內(nèi)容復(fù)制到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); } }本章作業(yè)

                      1.編程題 按要求實現(xiàn): (1) 封裝一個新聞類,包含標(biāo)題和內(nèi)容屬性,提供get、set方法,重寫toString方法,打印對象時只打印標(biāo)題;

                      (2) 只提供一個帶參數(shù)的構(gòu)造器,實例化對象時,只初始化標(biāo)題;并且實例化兩個對象:新聞一:新冠確診病例超千萬,數(shù)百萬印度教信徒赴恒河“圣浴”引民眾擔(dān)憂 新聞二:男子突然想起2個月前釣的魚還在網(wǎng)兜里,撈起一看趕緊放生

                      (3) 將新聞對象添加到ArrayList集合中,并且進(jìn)行倒序遍歷;

                      (4) 在遍歷集合過程中,對新聞標(biāo)題進(jìn)行處理,超過15字的只保留前15個,然后在后邊加“…."

                      (5)在控制臺打印遍歷出經(jīng)過處理的新聞標(biāo)題;

                      package com.hspedu.homework; import java.util.ArrayList; @SuppressWarnings({"all"}) public class Homework01 { public static void main(String[] args) { ArrayList arrayList = new ArrayList(); arrayList.add(new News("新冠確診病例超千萬,數(shù)百萬印度教信徒赴恒河\"圣浴\"引民眾擔(dān)憂")); arrayList.add(new News("男子突然想起2個月前釣的魚還在網(wǎng)兜里,撈起一看趕緊放生")); int size = arrayList.size(); for (int i = size - 1; i >= 0; i--) { //System.out.println(arrayList.get(i)); News news = (News)arrayList.get(i); System.out.println(processTitle(news.getTitle())); } } //專門寫一個方法,處理現(xiàn)實新聞標(biāo)題 process處理 public static String processTitle(String title) { if(title == null) { return ""; } if(title.length() > 15) { return title.substring(0, 15) + "..."; //[0,15) } else { return title; } } } /** * 按要求實現(xiàn): * (1) 封裝一個新聞類,包含標(biāo)題和內(nèi)容屬性,提供get、set方法,重寫toString方法,打印對象時只打印標(biāo)題; * (2) 只提供一個帶參數(shù)的構(gòu)造器,實例化對象時,只初始化標(biāo)題;并且實例化兩個對象: * 新聞一:新冠確診病例超千萬,數(shù)百萬印度教信徒赴恒河“圣浴”引民眾擔(dān)憂 * 新聞二:男子突然想起2個月前釣的魚還在網(wǎng)兜里,撈起一看趕緊放生 * (3) 將新聞對象添加到ArrayList集合中,并且進(jìn)行倒序遍歷; * (4) 在遍歷集合過程中,對新聞標(biāo)題進(jìn)行處理,超過15字的只保留前15個,然后在后邊加“…” * (5) 在控制臺打印遍歷出經(jīng)過處理的新聞標(biāo)題; */ class News { private String title; private String content; public News(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; } @Override public String toString() { return "News{" + "title='" + title + '\'' + '}'; } }

                      2.編程題

                      1.add:添加單個元素

                      2.remove:刪除指定元素

                      3.contains:查找元素是否存在

                      4.size:獲取元素個數(shù)

                      5.isEmpty:判斷是否為空6.clear:清空

                      7.addAll:添加多個元素

                      8.containsAl:查找多個元素是否都存在

                      9.removeAll:刪除多個元素

                      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:獲取元素個數(shù) 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); //相當(dāng)于清空 //* 使用增強(qiáng)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:獲取元素個數(shù) * 5.isEmpty:判斷是否為空 * 6.clear:清空 * 7.addAll:添加多個元素 * 8.containsAll:查找多個元素是否都存在 * 9.removeAll:刪除多個元素 * 使用增強(qiáng)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; } @Override public String toString() { return "Car{" + "name='" + name + '\'' + ", price=" + price + '}'; } }

                      3.編程題,按要求完成下列任務(wù)

                      4.簡答題

                      (1) HashSet的去重機(jī)制:hashCode() + equals() ,底層先通過存入對象,進(jìn)行運算得到一個hash值,通過hash值得到對應(yīng)的索引,如果發(fā)現(xiàn)table索引所在的位置,沒有數(shù)據(jù),就直接存放如果有數(shù)據(jù),就進(jìn)行equals比較[遍歷比較],如果比較后,不相同,就加入,否則就不加入。

                      (2)TreeSet的去重機(jī)制:如果你傳入了一個Comparator匿名對象,就使用實現(xiàn)的compare去重,如果方法返回0,就認(rèn)為是相同的元素/數(shù)據(jù),就不添加,如果你沒有傳入一個Comparator匿名對象,則以你添加的對象實現(xiàn)的Compareable接口的compareTo去重。

                      5.代碼分析題

                      6.下面的代碼輸出什么?這道題很有意思,稍不注意就掉進(jìn)陷阱.

                      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();//ok Person p1 = new Person(1001,"AA");//ok Person p2 = new Person(1002,"BB");//ok set.add(p1);//ok set.add(p2);//ok p1.name = "CC"; // 修改了原p1的name為CC set.remove(p1); // 可能刪除失敗,這里刪除p1按照當(dāng)前的1001和CC計算hash,那么這對應(yīng)的位置與原p1不同 System.out.println(set);// 2 set.add(new Person(1001,"CC")); // 可以添加成功,添加到本來要刪除的p1(實際刪除失敗)的位置 System.out.println(set);// 3 set.add(new Person(1001,"AA")); // 可以添加,因為原p1已經(jīng)修改了 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; } @Override public 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); } @Override public int hashCode() { return Objects.hash(name, id); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", id=" + id + '}'; } }

                      7.試寫出Vector和ArrayList的比較?