(九)集合

  1. 集合框架概述
    • 集合框架的做用:在實際的開發過程當中,咱們常常會對一組相同類型的數據進行統一管理操做,到目前爲止,咱們可使用數組結構、鏈表結構、二叉樹結構來實現。數組最大的問題在於數組中的元素個數是固定的,要實現動態數組,畢竟仍是比較麻煩;本身實現鏈表或二叉樹結構來管理對象更是不方便。因此在JDK1.2版本後,Java完整的提供了類集合的概念,封裝了一組強大的、很是方便的集合框架API,讓咱們在開發中大大的提升了效率前端

    • 集合中分爲三大接口:Collection、Map、Iteratorjava

    • 集合框架的接口和類在java.util包中web

    • 集合框架結構圖:
      在這裏插入圖片描述算法

    • Collection接口express

      • Collection層次結構中的根接口。Collection表示一組對象,這些對象也稱爲collection的元素。一些collection容許有重複的元素,而另外一些則不容許。一些collection是有序的,而另外一些則是無序的。JDK不提供此接口的任何直接實現:它提供更具體的子接口(如SetList)實現。此接口一般用來傳遞collection,並在須要最大廣泛性的地方操做這些collection編程

      • 接口的定義:後端

        public interface Collection<E> extends Iterable<E>
      • List接口:設計模式

        • 有序的,能夠重複的
        • 容許多個null元素
        • 具體的實現類:ArrayList、VectorLinkedLIst
      • Set接口:數組

        • 無序的(不保證順序),不容許重複
        • 只容許存在一個null元素
        • 具體的實現類:HashSet、TreeSetLinkedHashSet
    • Map接口緩存

      • 接口的定義:

        public interface Map<K, V>
      • 具體的實現類:HashMap、TreeMap、LinkedHashMapHashtable

  2. 集合框架List接口
    public interface List<E> extends Collection<E>
    // 有序的 collection(也稱爲序列)。此接口的用戶能夠對列表中每一個元素的插入位置進行精確地控制。用戶能夠根據元素的整數索引(在列表中的位置)訪問元素,並搜索列表中的元素
    • ArrayList

      public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
      • List接口的大小是可變數組的實現。實現了全部可選列表操做,並容許包括null在內的全部元素。除了實現List接口外,此類還提供了一些方法來操做內部用來存儲列表的數組的大小

      • 示例:

        import java.util.ArrayList;
        import java.util.List;
        
        /** * @author xiao兒 * @date 2019/9/1 14:09 * @Description ListDemo * <p> * Collection 接口:用於存儲單個對象的集合 * List接口: * 1.有序的 * 2.容許多個null元素 * 3.具體的實現類:ArrayList、Vector、LinkedList */
        public class ArrayListDemo {
            public static void main(String[] args) {
                arrayList();
            }
        
            /** * ArrayList * 1.實現原理:採用動態對象數組實現,默認的構造方法建立了一個空數組 * 2.第一次添加元素,擴充容量爲10,以後的擴充算法:原來數組大小 + 原來數組大小的一半 * 3.不適合進行刪除或者插入操做 * 4.爲了防止數組動態的擴充次數過多,建議建立 ArrayList 時,給定初始容量 * 5.線程不安全,適合在單線程訪問時使用 * JDK1.2開始 */
            private static void arrayList() {
                // 使用集合來存儲多個不一樣類型的元素(對象),那麼在處理時會比較麻煩,在實際開發中,不建議這樣使用
                // 在一個集合中存儲相同的類型的對象
                List<String> list = new ArrayList<>();
                list.add("旺仔");
                list.add("真果粒");
                list.add("蒙牛");
                list.add("銀橋");
                // list.add(10);
        
                // 遍歷集合
                int size = list.size();
                for (int i = 0; i < size; i++) {
                    System.out.println(list.get(i));
                }
        
                System.out.println("旺仔是否存在於list中:" + list.contains("旺仔"));
                list.remove("銀橋");
                System.out.println("list_size:" + list.size());
        
                String[] array = list.toArray(new String[]{});
                for (String str : array) {
                    System.out.println(str);
                }
            }
        }
    • Vector

      • 示例:

        import java.util.Vector;
        
        /** * @author xiao兒 * @date 2019/9/1 16:46 * @Description VectorDemo */
        public class VectorDemo {
            public static void main(String[] args) {
                vector();
            }
        
            /** * Vector * 1.實現原理:採用動態對象數組實現,默認構造方法建立了一個大小爲10的對象數組 * 2.擴充的算法:當增量爲0時,擴充爲原來大小的兩倍,當增量大於0時,擴充爲原來大小+增量 * 3.不適合刪除或插入操做 * 4.爲了防止數組動態擴充次數過多,建議建立 Vector 時給定初始容量 * 5.線程安全,適合在多線程訪問時使用,在單線程下使用效率較低 */
            private static void vector() {
                Vector<String> vector = new Vector<>();
                vector.add("旺仔");
                vector.add("真果粒");
                vector.add("蒙牛");
                vector.add("銀橋");
        
                int size = vector.size();
                for (int i = 0; i < size; i++) {
                    System.out.println(vector.get(i));
                }
            }
        }
    • LinkedList

      public class LindedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
      • List接口是鏈表列表實現。實現全部可選的列表的操做,而且容許全部元素(包括null)。除了實現List接口外,LinkedList類還爲在列表的開頭及結尾get、removeinsert元素提供了統一的命名方法

      • 示例:

        import java.util.LinkedList;
        
        /** * @author xiao兒 * @date 2019/9/1 17:16 * @Description LinkedListDemo */
        public class LinkedListDemo {
            public static void main(String[] args) {
                linkedList();
            }
        
            /** * LinkedList * 1.實現原理:採用雙向鏈表結構實現 * 2.適合插入或刪除操做,性能高 * 3.線程不安全 */
            private static void linkedList() {
                LinkedList<String> linkedList = new LinkedList<>();
                linkedList.add("旺仔");
                linkedList.add("真果粒");
                linkedList.add("蒙牛");
                linkedList.add("銀橋");
        
                int size = linkedList.size();
                for (int i = 0; i < size; i++) {
                    System.out.println(linkedList.get(i));
                }
            }
        }
    • 如何選擇ArrayList、VectorLinkedList

      • 安全性問題:Vector線程安全,但在使用中會使用工具類使得ArrayList線程安全
      • 是否頻繁插入或刪除操做:LinkedList
      • 是不是存儲後遍歷:ArrayList
  3. 集合框架Set接口
    public interface Set<E> extends Collection<E>
    // 一個不包含重複元素的collection。更確切的說,set不包含知足e1.equals(e2)的元素對e1和e2,而且最多包含一個null元素。正如其名成所暗示的,此接口模仿了數學上的set抽象
    • HashSet

      public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
      • 類實現Set接口,有哈希表(其實是一個HashMap實例)支持。它不保證set的迭代順序;特別是它不保證該順序恆久不變。此類容許使用null元素

      • 示例:

        // Cat
        /** * @author xiao兒 * @date 2019/9/1 18:33 * @Description Cat */
        public class Cat {
            private String name;
            private int age;
            private int id;
        
            public Cat() {
            }
        
            public Cat(String name, int age, int id) {
                this.name = name;
                this.age = age;
                this.id = id;
            }
        
            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;
            }
        
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            @Override
            public String toString() {
                return "Cat{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", id=" + id +
                        '}';
            }
        
            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (!(o instanceof Cat)) return false;
        
                Cat cat = (Cat) o;
        
                if (age != cat.age) return false;
                if (id != cat.id) return false;
                return name != null ? name.equals(cat.name) : cat.name == null;
            }
        
            @Override
            public int hashCode() {
                int result = name != null ? name.hashCode() : 0;
                result = 31 * result + age;
                result = 31 * result + id;
                return result;
            }
        }
        
        // HashSetDemo
        import java.util.Arrays;
        import java.util.HashSet;
        import java.util.Set;
        
        /** * @author xiao兒 * @date 2019/9/1 18:03 * @Description HashSetDemo * * Set 接口: * 1.無序的(不保證順序) * 2.不容許重複元素 * 3.能夠存在一個null元素 * 4.具體實現類:HashSet、TreeSet 和 LinkedHashSet */
        public class HashSetDemo {
            public static void main(String[] args) {
                hashSet();
            }
        
            /** * HashSet * 1.實現原理:基於哈希表(HashMap)實現 * 2.不容許重複元素,能夠有一個null元素 * 3.不保證順序恆久不變 * 4.添加元素時把元素做爲 HashMap 的key存儲,HashMap的value使用一個固定的Object對象 * 5.排除重複元素是經過equals來檢查對象是否相同 * 6.判斷兩個對象是否相同:先判斷兩個對象的hashCode是否相同(若是兩個對象的hashCode相同,不必定是同一對象,若是不一樣, * 那必定不是同一個對象),若是不一樣則兩個對象不是同一個對象,若是相同,還要進行equals判斷,equals相同則是同一個對象, * 不一樣則不是同一個對象 * 7.自定義對象要認爲屬性值都相同時爲同一個對象,有這種需求時,那麼咱們須要重寫所在類的hashCode和equals方法 * * 小結: * (1)哈希表的存儲結構:數組+鏈表(數組裏的每個元素以鏈表中的形式存儲) * (2)若是把對象存儲到哈希表中,先計算對象的hashCode值,在對數組長度求餘數,來決定對象要存儲在數組中的那個位置 * (3)解決hashSet中的重複值使用的方式是:第6點 */
            private static void hashSet() {
                Set<String> hashSet = new HashSet<>();
                hashSet.add("旺仔");
                hashSet.add("真果粒");
                hashSet.add("蒙牛");
                hashSet.add("銀橋");
                hashSet.add("旺仔");
        
                System.out.println(hashSet.size());
        
                String[] strings = hashSet.toArray(new String[]{});
                for (String s : strings) {
                    System.out.println(s);
                }
                System.out.println(Arrays.toString(strings));
        
                Cat cat = new Cat("miaomiao", 5, 1);
                Cat cat1 = new Cat("huahua", 2, 3);
                Cat cat2 = new Cat("tom", 4, 2);
                Cat cat3 = new Cat("miaomiao", 5, 4);
                Cat cat4 = new Cat("beibei", 3, 3);
                Set<Cat> catSet = new HashSet<>();
                catSet.add(cat);
                catSet.add(cat1);
                catSet.add(cat2);
                catSet.add(cat3);
                catSet.add(cat4);
                catSet.add(cat);
                System.out.println("catSet的長度:" + catSet.size());
        
                for (Cat c : catSet) {
                    System.out.println(c);
                }
                System.out.println("cat的hashCode是:" + cat.hashCode() % 16);
                System.out.println("cat1的hashCode是:" + cat1.hashCode() % 16);
                System.out.println("cat2的hashCode是:" + cat2.hashCode() % 16);
                System.out.println("cat3的hashCode是:" + cat3.hashCode() % 16);
                System.out.println("cat4的hashCode是:" + cat4.hashCode() % 16);
            }
        }
      • hashCode深刻分析:

        hashCode()方法,在Object類中定義以下:
        public native int hashCode();
        hashCode()是本地方法,它的實現是根據本地機器相關,固然咱們能夠在本身寫的類中覆蓋hashCode()方法,好比String、Integer、Double...等等這些類都是覆蓋了hashCode()方法的
      • Java的集合中,判斷兩個對象是否相等的規則是:

        • 判斷兩個對象的hashCode是否相等
          • 若是不相等,認爲兩個對象也不相等,結束
          • 若是相等,則轉下一步
        • 判斷兩個對象用equals運算是否相等
          • 若是不相等,認爲兩個對象也不相等
          • 若是相等,認爲兩個對象相等
          • equals()是判斷兩個對象是否相等的關鍵)
    • TreeSet

      public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable
      • 基於TreeMapNavigableSet實現。使用元素的天然順序對元素進行排序,或者根據建立set時提供的Comparator進行排序,具體取決於使用的構造方法

      • 示例:

        // CatComparator
        import java.util.Comparator;
        
        /** * @author xiao兒 * @date 2019/9/1 22:05 * @Description CatComparator */
        public class CatComparator implements Comparator<Cat> {
            @Override
            public int compare(Cat o1, Cat o2) {
                return o1.getAge() - o2.getAge();
            }
        }
        
        // TreeSetDemo
        import java.util.TreeSet;
        
        /** * @author xiao兒 * @date 2019/9/1 21:55 * @Description TreeSetDemo */
        public class TreeSetDemo {
            public static void main(String[] args) {
                treeSet();
            }
        
            /** * TreeSet * 1.有序的,基於 TreeMap(二叉樹數據結構),對象須要比較大小,經過對象比較器 Comparator,對象比較器還能夠去除重複元素 * 若是自定義的數據類,沒有實現比較器接口,將沒法添加到 TreeSet 集合中 */
            private static void treeSet() {
                TreeSet<Cat> treeSet = new TreeSet<>(new CatComparator());
                Cat cat = new Cat("miaomiao", 5, 1);
                Cat cat1 = new Cat("huahua", 2, 3);
                Cat cat2 = new Cat("tom", 3, 2);
                Cat cat3 = new Cat("miaomiao", 4, 4);
                Cat cat4 = new Cat("beibei", 3, 3);
                treeSet.add(cat);
                treeSet.add(cat1);
                treeSet.add(cat2);
                treeSet.add(cat3);
                treeSet.add(cat4);
        
                System.out.println(treeSet.size());
        
                for (Cat c : treeSet) {
                    System.out.println(c);
                }
            }
        }
    • LinkedHashSet

      public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable
      • 具備可預知迭代順序的Set接口的哈希表和鏈表列表實現。此實現與HashSet的不一樣之處在於,後者維護着一個運行於全部條目的雙重鏈表列表。此連接列表定義了迭代順序,即按照將元素插入到set中的順序(插入順序)進行迭代。注意,插入順序不受在set中從新插入元素的影響。(若是在s.contains(e)返回true後當即調用s.add(e),則元素e會被從新插入到set s

      • 示例:

        import java.util.LinkedHashSet;
        
        /** * @author xiao兒 * @date 2019/9/1 22:23 * @Description LinkedHashSetDemo */
        public class LinkedHashSetDemo {
            public static void main(String[] args) {
                linkedHashSet();
            }
        
            /** * LinkedHashSet * 1.實現原理:哈希表和鏈表列表實現 */
            private static void linkedHashSet() {
                LinkedHashSet<Cat> cats = new LinkedHashSet<>();
                Cat cat = new Cat("miaomiao", 5, 1);
                Cat cat1 = new Cat("huahua", 2, 3);
                Cat cat2 = new Cat("tom", 3, 2);
                Cat cat3 = new Cat("miaomiao", 4, 4);
                Cat cat4 = new Cat("beibei", 3, 3);
                cats.add(cat);
                cats.add(cat1);
                cats.add(cat2);
                cats.add(cat3);
                cats.add(cat4);
        
                for (Cat c : cats) {
                    System.out.println(c);
                }
            }
        }<font face="楷體" size=4></font>
    • 如何選擇HashSet、TreeSetLinkedHashSet

      • 若是不要保證元素有序,使用TreeSet
      • 若是不須要元素有序並且不須要保證插入順序,使用HashSet
      • 若是不須要保證元素有序,可是須要保證插入順序,使用LinkedHashSet
  4. 集合框架Iterator接口
    • 集合輸出:

      • Iterator(使用率最高)
      • ListIterator
      • Enumeration
      • foreach(1.5以後使用率最高)
    • 示例:

      import java.util.*;
      
      /** * @author xiao兒 * @date 2019/9/1 23:33 * @Description IteratorDemo */
      public class IteratorDemo {
          public static void main(String[] args) {
              List<Cat> list = new ArrayList<>();
              Cat cat = new Cat("miaomiao", 5, 1);
              Cat cat1 = new Cat("huahua", 2, 3);
              Cat cat2 = new Cat("tom", 4, 2);
              Cat cat3 = new Cat("miaomiao", 5, 4);
              Cat cat4 = new Cat("beibei", 3, 3);
              list.add(cat);
              list.add(cat1);
              list.add(cat2);
              list.add(cat3);
              list.add(cat4);
      
              foreach(list);
              System.out.println("-----------------");
              iterator(list);
              System.out.println("-----------------");
              enumeration();
          }
      
          // foreach(1.5)
          private static void foreach(Collection<Cat> cats) {
              for (Cat c : cats) {
                  System.out.println(c);
              }
          }
      
          // iterator(1.5以前統一的迭代集合方式)
          private static void iterator(Collection<Cat> cats) {
              Iterator<Cat> iter = cats.iterator();
              while (iter.hasNext()) {
                  System.out.println(iter.next());
              }
          }
      
          // enumeartion
          private static void enumeration() {
              Vector<String> vector = new Vector<>();
              vectorlist.forEach((String s) -> {
                  System.out.println(s);
              });.add("Tom");
              vector.add("Jack");
              vector.add("Job");
              vector.add("Lily");
      
              Enumeration<String> enumeration = vector.elements();
              while (enumeration.hasMoreElements()) {
                  System.out.println(enumeration.nextElement());
              }
          }
      }
    • foreach

      • 在使用foreach輸出的時候要注意:建立集合時要指定操做泛型的類型

      • JDK1.8新特性:

        // no.1
        list.forEach((String s) -> {System.out.println(s);});
        // no.2
        list.forEach(s -> {System.out.println(s);});
        // no.3
        list.forEach(s -> System.out.println(s));
        // no.4
        list.forEach(System.out::println);
        // no.5
        list.forEach(new MyConsumer());// 本身寫一個類 MyConsumer 實現 Consumer 接口
  5. JDK1.8新特性
    • Consumer<T>接口:消費者接口

      import java.util.function.Consumer;
      
      /** * @author xiao兒 * @date 2019/9/2 8:31 * @Description ConsumerDemo */
      public class ConsumerDemo {
          public static void main(String[] args) {
              consumer();
          }
      
          // 消費者接口
          private static void consumer() {
              strToUpp("xiaoer", str -> System.out.println(str.toUpperCase()));
          }
      
          public static void strToUpp(String str, Consumer<String> consumer) {
              consumer.accept(str);
          }
      }
    • Function<T,R>接口:表示接受一個參數併產生結果的函數

      import java.util.function.Function;
      
      /** * @author xiao兒 * @date 2019/9/2 8:21 * @Description FunctionDemo */
      public class FunctionDemo {
          public static void main(String[] args) {
              function();
          }
      
          // 表示接受一個參數併產生結果的函數
          private static void function() {
              String s = strToUpp("xiaoer", str -> str.toUpperCase());
              System.out.println(s);
          }
      
          public static String strToUpp(String str, Function<String, String> f) {
              return f.apply(str);
          }
      }
    • Supplier<T>接口:表明結果供應商

      import java.util.ArrayList;
      import java.util.List;
      import java.util.function.Supplier;
      
      /** * @author xiao兒 * @date 2019/9/2 8:40 * @Description SupplierDemo */
      public class SupplierDemo {
          public static void main(String[] args) {
              supplier();
          }
      
          // 表明結果供應商
          private static void supplier() {
              List<Integer> list = getNums(10, () -> (int) (Math.random() * 100));
              list.forEach((i) -> {
                  System.out.println(i);
              });
              System.out.println("------------");
              list.forEach(System.out::println);
          }
      
          public static List<Integer> getNums(int num, Supplier<Integer> supplier) {
              List<Integer> list = new ArrayList<>();
              for (int i = 0; i < num; i++) {
                  list.add(supplier.get());
              }
              return list;
          }
      }
    • Predicate<T>接口:斷言接口

      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.List;
      import java.util.function.Predicate;
      
      /** * @author xiao兒 * @date 2019/9/2 8:50 * @Description PredicateDemo */
      public class PredicateDemo {
          public static void main(String[] args) {
              predicate();
          }
      
          // 斷言接口
          private static void predicate() {
              List<String> list = Arrays.asList("Lily", "Tom", "Job", "Curly");
              List<String> result = filter(list, s -> s.contains("C"));
              result.forEach(System.out::println);
          }
      
          private static List<String> filter(List<String> list, Predicate<String> predicate) {
              List<String> result = new ArrayList<>();
              for (String s : list) {
                  if (predicate.test(s)) {// 測試是否符合要求
                      result.add(s);
                  }
              }
              return result;
          }
      }
  6. JDK1.8新特性之Stream
    • 什麼是Stream

      • Stream是元素的集合,這點讓Stream看起來有些相似Iterator
      • 能夠支持順序和並行的對原Stream進行匯聚的操做
    • 咱們能夠把Stream當成一個高級版本的Iterator。原始版本的Iterator,用戶只能一個一個的遍歷元素並對其進行某些操做;高級版本的Stream,用戶只須要對其包含的元素執行什麼操做,好比「過濾掉長度大於10的字符串」、「獲取每一個字符串的首字母」等,具體這些操做如何應用到每一個元素上,就給Stream就行了

    • 示例:

      import java.util.Arrays;
      import java.util.List;
      import java.util.Optional;
      import java.util.function.BinaryOperator;
      import java.util.stream.Collectors;
      import java.util.stream.Stream;
      
      /** * @author xiao兒 * @date 2019/9/2 9:14 * @Description StreamDemo * <p> * Stream接口:不是存儲的數據結構,數據源能夠是一個集合,爲了函數式編程創造 * 惰式執行,數據只能被消費一次 * <p> * 兩種類型的操做方法: * 1.中間操做(生成一個 Stream) * 2.結束操做(執行計算操做) */
      public class StreamDemo {
          public static void main(String[] args) {
              // foreach方法
              Stream<String> stream = Stream.of("good", "good", "study", "day", "day", "up");
              // stream.forEach((str) -> {
              // System.out.println(str);
              // });
              // System.out.println("------------");
      
              // filter
              // stream.filter((s) -> s.length() > 3).forEach(System.out::println);
              // System.out.println("----------------");
      
              // distinct
              // stream.distinct().forEach(s -> System.out.println(s));
      
              // map
              // stream.map(s -> s.toUpperCase()).forEach(s -> System.out.println(s));
      
              // flatMap
              // Stream<List<Integer>> num = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5));
              // num.flatMap(list -> list.stream()).forEach(s -> System.out.println(s));
      
              // reduce
              // Optional<String> optionalS = stream.reduce((s1, s2) -> s1.length() >= s2.length() ? s1 : s2);
              // System.out.println(optionalS.get());
      
              // collect
              List<String> list = stream.collect(Collectors.toList());
              list.forEach(s -> System.out.println(s));
      
              // :: 方法的引用
              // 引用靜態的方法 Integer::valueOf
              // 引用對象的方法 list::add
              // 引用構造方法 Arrayalist::new
          }
      }
  7. 集合框架Map接口
    public interface Map<K, V>
    // 將鍵映射到值得對象,一個映射不能包含重複的鍵;每一個鍵最多隻能映射到一個值
    • HashMap

      public class HashMap<K, V> extends AbstractMap<K,V> implements Map<K, V>, Cloneable, Serializable
      • 基於哈希表的Map接口的實現。此實現提供全部可選的映射操做,並容許使用null值和null鍵。(除了非同步和容許使用null以外,HashMap類與Hashtable大體相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變

      • 示例:

        import java.util.Collection;
        import java.util.HashMap;
        import java.util.Map;
        import java.util.Set;
        import java.util.stream.Stream;
        
        /** * @author xiao兒 * @date 2019/9/2 10:00 * @Description HashMapDemo * * Map接口: * 1.鍵值對存儲一組對象 * 2.Key保證惟一,不能重複;Value能夠重複 * 3.具體的實現類:HashMap、TreeMap 和 Hashtable LinkedHashMap */
        public class HashMapDemo {
            public static void main(String[] args) {
                hashMap();
            }
        
            /** * HashMap 的實現原理: * 1.基於哈希表(數組+鏈表+二叉樹(紅黑樹)) * 2.默認負載因子:0.75,默認數組大小是16 * 3.把對象存儲到哈希表中,如何存儲? * 把key對象經過hash方法計算哈希值,而後用哈希值對數組長度取餘(默認是16),來決定該key對象在數組中存儲的位置, * 當這個位置有多個對象時,以鏈表存儲,JDK1.8後,當鏈表長度大於8時,鏈表將轉換爲二叉樹(紅黑樹) * 這樣的目的:爲了取值更快,存儲的數據量越大,性能的表現越明顯 * 4.擴充原理:當數組的容量超過了75%,那麼表示該數組須要擴充,如何擴充? * 擴充的算法:當前的數組容量<<1(至關因而乘以2),擴大1倍,擴充次數過多會影響性能,每次擴充表示哈希表從新散列 * (從新計算每一個對象的存儲位置),咱們在開發中儘可能要減小擴充次數帶來的性能問題 * 5.線程不安全,適合在單線程中使用 */
            private static void hashMap() {
                Map<Integer, String> map = new HashMap<>();
                map.put(1, "Tom");
                map.put(2, "Jack");
                map.put(3, "Lily");
                map.put(4, "Bin");
        
                System.out.println("size=" + map.size());
                // 從map中取值
                System.out.println(map.get(1));
                System.out.println("------------");
        
                // map的遍歷
                Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
                for (Map.Entry e : entrySet) {
                    System.out.println(e.getKey() + "->" + e.getValue());
                }
                System.out.println("------------");
        
                // keySet:遍歷鍵,能夠經過鍵查找值
                Set<Integer> keys = map.keySet();
                for (Integer i : keys) {
                    String value = map.get(i);
                    System.out.println(i + "->" + value);
                }
                System.out.println("------------");
        
                // values:遍歷值,不能經過值查找鍵
                Collection<String> values =  map.values();
                for (String s : values) {
                    System.out.println(s);
                }
                System.out.println("------------");
        
                // foreach
                map.forEach((key, value) -> System.out.println(key + "->" + value));
        
                System.out.println(map.containsKey(7));
                System.out.println("------------");
        
                // hash
                Integer key = 1314;
                int h;
                int hashCode = (key.hashCode());
                int hash = (h = key.hashCode()) ^ (h >>> 16);
                int count = hash & 15;
                System.out.println(hashCode);
                System.out.println(hash);
                System.out.println(count);
            }
        }
    • TreeMap

      public class TreeMap<K, V> extends AbstractMap<K, V> implements NavigableMap<K, V>, Cloneable, Serializable
      • 基於紅黑樹(Red-Black tree)的NavigableMap實現。該映射根據其鍵的天然順序進行排序,或者根據建立映射時提供的Comparator進行排序,具體取決於使用的構造方法

      • 示例:

        // Dog
        /** * @author xiao兒 * @date 2019/9/2 18:13 * @Description Dog */
        public class Dog {
            private int id;
            private String name;
            private int age;
        
            public Dog() {
            }
        
            public Dog(int id, String name, int age) {
                this.id = id;
                this.name = name;
                this.age = age;
            }
        
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public int getAge() {
                return age;
            }
        
            public void setAge(int age) {
                this.age = age;
            }
        
            @Override
            public String toString() {
                return "Dog{" +
                        "id=" + id +
                        ", name='" + name + '\'' +
                        ", age=" + age +
                        '}';
            }
        }
        
        // DogComparator
        import java.util.Comparator;
        
        /** * @author xiao兒 * @date 2019/9/2 18:17 * @Description DogComparator */
        public class DogComparator implements Comparator<Dog> {
        
            @Override
            public int compare(Dog o1, Dog o2) {
                return o1.getId() - o2.getId();
            }
        }
        
        // TreeMapDemo
        import java.util.Map;
        import java.util.TreeMap;
        
        /** * @author xiao兒 * @date 2019/9/2 18:09 * @Description TreeMapDemo */
        public class TreeMapDemo {
            public static void main(String[] args) {
                treeMap();
            }
        
            /** * TreeMap * 1.基於二叉樹的紅黑樹實現 */
            private static void treeMap() {
                Map<String, String> map = new TreeMap<>();
                map.put("one", "Lily");
                map.put("two", "Tom");
                map.put("three", "Bin");
        
                map.forEach((key, value) -> System.out.println(key + "->" + value));
                System.out.println("---------------");
        
                Map<Dog, String> dogs = new TreeMap<>(new DogComparator());
                dogs.put(new Dog(1, "二哈", 3), "dog1");
                dogs.put(new Dog(2, "三哈", 2), "dog2");
                dogs.put(new Dog(3, "四哈", 4), "dog3");
        
                dogs.forEach((dog, value) -> System.out.println(dog + "->" + value));
            }
        }
    • Hashtable

      public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, Cloneable, Serializable
      • 此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非null對象均可以用做鍵或值。爲了成功地在哈希表中存儲和獲取對象,用做鍵的對象必須實現hashCode方法和equals方法

      • 示例:

        import java.util.Hashtable;
        import java.util.Map;
        
        /** * @author xiao兒 * @date 2019/9/2 17:34 * @Description Hashtable */
        public class HashtableDemo {
            public static void main(String[] args) {
                hashtable();
            }
        
            /** * Hashtable * 1.JDK1.0開始 * 2.基於哈希表實現(數組+鏈表) * 3.默認數組大小是11,加載因子0.75 * 4.擴充方式:原數組大小<<1(*2) + 1 * 5.線程安全的,用在多線程訪問時 */
            private static void hashtable() {
                Map<String, String> hashtable = new Hashtable<>();
                hashtable.put("one", "Lily");
                hashtable.put("two", "Tom");
                hashtable.put("three", "Bin");
        
                hashtable.forEach((key, value) -> System.out.println(key + "->" + value));
            }
        }
    • LinkedHashMap

      public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V>
      • Map接口的哈希表和連接列表實現,具備可預知的迭代順序。此實現與HashMap的不一樣之處在於,後者維護着一個運行於全部條目的雙重連接列表

      • 示例:

        import java.util.LinkedHashMap;
        import java.util.Map;
        
        /** * @author xiao兒 * @date 2019/9/2 17:59 * @Description LinkedHashMapDemo */
        public class LinkedHashMapDemo {
            public static void main(String[] args) {
                linkedHashMap();
            }
        
            /** * LinkedHashMap * 1.LinkedHashMap 是 HashMap 的子類,因爲 HashMap 不能保證順序恆久不變,此類使用雙重鏈表來維護元素添加的順序 */
            private static void linkedHashMap() {
                Map<String, String> map = new LinkedHashMap<>();
                map.put("one", "Lily");
                map.put("two", "Tom");
                map.put("three", "Bin");
        
                map.forEach((key, value) -> {
                    System.out.println(key + "->" + value);
                });
            }
        }
    • JDK1.8Map新特性

      • Map接口中的新方法:在JDK1.8中新增了許多default方法

      • 示例:

        import java.util.HashMap;
        import java.util.Map;
        
        /** * @author xiao兒 * @date 2019/9/2 18:38 * @Description MapNewMethodDemo */
        public class MapNewMethodDemo {
            public static void main(String[] args) {
                Map<Integer, String> map = new HashMap<>();
                map.put(1, "Jack");
                map.put(2, "Tom");
                map.put(3, "Lily");
        
                String str = map.getOrDefault(4, "null");
                System.out.println(str);
                System.out.println("---------------");
        
                // String val = map.put(3, "Vince");
                // 只會添加不存在相同key的值
                String val = map.putIfAbsent(3, "Vince");
                System.out.println(val);
                map.forEach((key, value) -> System.out.println(key + "->" + value));
                System.out.println("---------------");
        
                // 根據鍵和值都匹配時纔會刪除
                boolean b = map.remove(1, "Lily");
                System.out.println("是否刪除:" + b);
                System.out.println("----------------");
        
                // 替換
                String string  = map.replace(3, "Vince");
                System.out.println(string);
                map.forEach((key, value) -> System.out.println(key + "->" + value));
                System.out.println("-----------------");
        
                // 替換
                boolean b1 = map.replace(3, "Vince", "Lily");
                System.out.println("是否替換成功:" + b1);
                System.out.println("------------------");
        
                String string1 = map.compute(1, (key, value) -> value + "1");
                System.out.println(string1);
                System.out.println("-------------------");
        
                String string2 = map.computeIfAbsent(4, value -> value + "test");
                System.out.println(string2);
                System.out.println("-------------------");
        
                String string3 = map.merge(1, "888", (oldValue, newValue) -> oldValue.concat(newValue));
                System.out.println(string3);
            }
        }
  8. Collections工具類
    • 排序操做(主要針對List接口相關)

      // 反轉指定List集合中元素的順序
      reverse(List list);
      // 對List中的元素進行隨機排序(洗牌)
      shuffle(List list);
      // 對List裏的元素根據天然升序排序
      sort(List list);
      // 自定義比較器進行排序
      sort(List list, Comparator c);
      // 將指定List集合中i處的元素和j處元素進行交換
      swap(List list, int i, int j);
      // 將全部元素向右移位指定長度,若是distance等於size那麼結果不變
      rotate(List list, int distance);
    • 查找和替換(主要針對Collection接口相關)

      // 使用二分搜索法,以得到指定對象在List中的索引,前提是集合已經排序
      binarySearch(List list, Object key);
      // 返回最大元素
      max(Collection coll);
      // 根據自定義比較器,返回最大元素
      max(Collection coll, Comparator comp);
      // 返回最小元素
      min(Collection coll);
      // 根據自定義比較器,返回最小元素
      min(Collection coll, Comparator comp);
      // 使用指定對象填充
      fill(List list, Object obj);
      // 返回指定集合中指定對象出現的次數
      frequency(Collection Object o);
      // 替換
      replaceAll(List list, Object old, Object new);
    • 同步控制

      • Collections工具類中提供了多個synchronizedXxx方法,該方法返回指定集合對象對應的同步對象,從而解決多線程併發訪問集合時線程的安全問題。HashSet、ArrayList、HashMap都是線程不安全的,若是須要考慮同步,則使用這些方法。這些方法主要有:synchronizedSet、synchronizedSortedSet、synchronizedList、synchronizedMap、synchronizedSortedMap
      • 注意:在使用迭代方法遍歷集合對象時須要手工同步返回的集合
    • 設置不可變集合:Collections有三類方法可返回一個不可變集合

      // 返回一個空的不可變的集合對象
      emptyXxx();
      // 返回一個只包含指定對象的,不可變的集合對象
      singletonXxx();
      // 返回指定集合對象的不可變視圖
      unmodifiableXxx();
    • 其餘

      // 若是兩個指定collection中沒有相同的元素,則返回true
      disjoint(Collection<?> c1, Collection<?> c2);
      // 一種方便的方式,將全部指定元素添加到指定collection中
      addAll(Collection<? super T> c, T...a);
      // 返回一個比較器,它強行反轉指定比較器的順序。若是指定比較器爲null,則此方法等同於reverseOrder()(換句話說,它返回一個比較器,該比較器將強行反轉實現Comparable接口那些對象collection上的天然順序)
      Comparator<T> reverseOrder(Comparator<T> cmp);
  9. Optional容器類
    • 這是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象

      // 爲非null的值建立一個Optional
      of
      // 爲指定的值建立一個Optional,若是指定的值爲null,則返回一個空的Optional
      ofNUllable
      // 若是值存在返回true,不然返回false
      isPresent
      // 若是Optional有值則將其返回,不然拋出NoSuchElementException
      get
      // 若是Optional實例有值則爲其調用consumer,不然不作處理
      ifPresent
      // 若是有值則將其返回,不然返回指定的其餘值
      orElse
      // orElseGet與orElse方法相似,區別在於獲得的默認值。orElse方法將傳入的字符串做爲默認值,orElseGet方法能夠給接受Supplier接口的實現用來生成默認值
      orElseGet
      // 若是有值則將其返回,不然拋出supplier接口建立的異常
      orElseThrow
      // 若是有值,則對其執行調用mapping函數獲得返回值。若是返回值不爲null,則建立包含mapping返回值的Optional做爲map方法返回值,不然返回空Optional
      map
      // 若是有值,爲其執行mapping函數返回Optional類型返回值,不然返回空Optional。flatMap與map(Function)方法相似,區別在於flatMap中的mapper返回值必須是Optional。調用結束時,flatMap不會對結果用Optional封裝
      flatMap
      // 若是有值而且知足斷言條件返回包含該值的Optional,不然返回空Optional
      filter
    • 示例:

      import java.util.Optional;
      import java.util.stream.Stream;
      
      /** * @author xiao兒 * @date 2019/9/3 7:50 * @Description OptionalDemo */
      public class OptionalDemo {
          public static void main(String[] args) {
              // 建立 Optional 對象的方式
              Optional<String> optional = Optional.of("Bin");
              Optional<String> optional2 = Optional.ofNullable("Bin");
              Optional<String> optional3 = Optional.empty();
      
              System.out.println(optional.isPresent());
              System.out.println(optional.get());
      
              optional.ifPresent(value -> System.out.println(value));
      
              System.out.println(optional.orElse("nihao"));
      
              System.out.println(optional.orElseGet(() -> "default"));
      
              // try {
              // System.out.println(optional3.orElseThrow(Exception::new));
              // } catch (Exception e) {
              // e.printStackTrace();
              // }
      
              Optional<String> optional4 = optional.map((value) -> value.toUpperCase());
              System.out.println(optional4.orElse("沒有"));
      
              Optional<String> optional5 = optional.flatMap((value) -> Optional.of(value.toUpperCase()));
              System.out.println(optional5.orElse("無"));
      
              Optional<String> optional6 = optional.filter((value) -> value.length() > 3);
              System.out.println(optional6.orElse("長度小於等於3"));
          }
      }
  10. Queue、Deque接口和Stack
  • Queue

    • 隊列(Queue)是一種特殊的線性表,是一種先進先出(FIFO)的數據結構。它只容許在表的前端front進行刪除操做,而在表的後端rear進行插入操做。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲對頭。隊列中沒有元素時,稱爲空隊列

    • 示例:

      import java.util.LinkedList;
      import java.util.Queue;
      
      /** * @author xiao兒 * @date 2019/9/3 8:14 * @Description QueueDemo * <p> * Queue接口:隊列,是一種先進先出的線性數據結構 * LinkedList 類實現了 Queue 接口 * 請求隊列,消息隊列 */
      public class QueueDemo {
          public static void main(String[] args) {
              queue();
          }
      
          private static void queue() {
              Queue<String> queue = new LinkedList<>();
              queue.add("Tom");
              queue.add("Lily");
              queue.add("Job");
              queue.add("Jack");
      
              System.out.println(queue.size());
              // 取出對頭,但並不刪除
              System.out.println(queue.peek());
              System.out.println(queue.size());
              // 移除對頭
              System.out.println(queue.poll());
              System.out.println(queue.size());
      
              System.out.println(queue);
          }
      }
  • Deque

    • 一個線性collection,支持在兩端插入和移除元素。此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列

    • 示例:

      import java.util.Deque;
      import java.util.LinkedList;
      
      /** * @author xiao兒 * @date 2019/9/3 8:25 * @Description DequeDemo * * Deque接口:雙端隊列 */
      public class DequeDemo {
          public static void main(String[] args) {
              deque();
          }
      
          private static void deque() {
              Deque<String> deque = new LinkedList<>();
              deque.add("Tom");
              deque.add("Job");
              deque.add("Jack");
              deque.add("Bin");
      
              System.out.println(deque.size());
      
              System.out.println(deque.getFirst());
              System.out.println(deque.getLast());
              System.out.println(deque.peekFirst());
              System.out.println(deque.peekLast());
          }
      }
  • Stack

    • 示例:

      import java.util.Stack;
      
      /** * @author xiao兒 * @date 2019/9/3 8:35 * @Description StackDemo * * Stack類:棧,先進後出的線性數據結構 */
      public class StackDemo {
          public static void main(String[] args) {
              stack();
          }
      
          private static void stack() {
              Stack<String> stack = new Stack<>();
              // 壓棧
              stack.push("Bin");
              stack.push("Jack");
              stack.push("Job");
              stack.push("Tom");
      
              System.out.println(stack.peek());
              System.out.println(stack.size());
              System.out.println(stack.pop());
              System.out.println(stack.size());
          }
      }
  1. 對象一對多與多對多關係
    • 一對多關係示例:

      // Teacher類
      import java.util.HashSet;
      
      /** * @author xiao兒 * @date 2019/9/3 8:53 * @Description Teacher * * one */
      public class Teacher {
          private String name;
          private int age;
          private String sex;
          private HashSet<Student> students = new HashSet<>();
      
          public Teacher() {
          }
      
          public Teacher(String name, int age, String sex) {
              this.name = name;
              this.age = age;
              this.sex = sex;
          }
      
          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;
          }
      
          public String getSex() {
              return sex;
          }
      
          public void setSex(String sex) {
              this.sex = sex;
          }
      
          public HashSet<Student> getStudents() {
              return students;
          }
      
          public void setStudents(HashSet<Student> students) {
              this.students = students;
          }
      
          @Override
          public String toString() {
              return "Teacher{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      ", sex='" + sex + '\'' +
                      '}';
          }
      }
      
      // Student類
      /** * @author xiao兒 * @date 2019/9/3 8:54 * @Description Student * * many */
      public class Student {
          private String name;
          private int age;
          private String sex;
          private Teacher teacher;
      
          public Student() {
          }
      
          public Student(String name, int age, String sex) {
              this.name = name;
              this.age = age;
              this.sex = sex;
          }
      
          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;
          }
      
          public String getSex() {
              return sex;
          }
      
          public void setSex(String sex) {
              this.sex = sex;
          }
      
          public Teacher getTeacher() {
              return teacher;
          }
      
          public void setTeacher(Teacher teacher) {
              this.teacher = teacher;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      ", sex='" + sex + '\'' +
                      '}';
          }
      }
      
      // OneToManyDemo
      /** * @author xiao兒 * @date 2019/9/3 8:53 * @Description OneToManyDemo */
      public class OneToManyDemo {
          public static void main(String[] args) {
              Teacher teacher = new Teacher("張老師", 18, "女");
              Student student = new Student("Tom", 13, "男");
              Student student1 = new Student("Job", 12, "男");
              Student student2 = new Student("Lily", 11, "女");
      
              // 關聯關係
              teacher.getStudents().add(student);
              teacher.getStudents().add(student1);
              teacher.getStudents().add(student2);
      
              student.setTeacher(teacher);
              student1.setTeacher(teacher);
              student2.setTeacher(teacher);
      
              print(teacher);
          }
      
          private static void print(Teacher teacher) {
              System.out.println(teacher.getName());
              for (Student student : teacher.getStudents()) {
                  System.out.println(student);
              }
          }
      }
    • 多對多關係:通常以一箇中間類,將一個多對多分解爲兩個一對多關係

  2. 迭代器設計模式
    • 提供一個方法按順序遍歷一個集合內的元素,而又不須要暴露該對象的內部表示
    • 應用場景:
      • 訪問一個聚合的對象,而不須要暴露對象的內部表示
      • 支持對聚合對象的多種遍歷
      • 對遍歷不一樣的對象,提供統一的接口
  3. guava對集合的支持
    • Guava工程包含了若干被GoogleJava項目普遍依賴的核心庫,例如:集合[collections]、緩存[caching]、原生類型支持[primitives support]、併發庫[concurrency libraries]、通用註解[common annotations]、字符串處理[string processing]I/O等等

    • JDK的擴展:

      • 不可變集合:用不變的集合進行防護性編程和性能提高
      • 新集合類型:multisets、multimaps、tables
      • 強大的集合工具類:提供java.util.Collections中沒有的集合工具
      • 擴展工具類:讓實現和擴展集合類變得更容易,好比建立Collection的裝飾器,或實現迭代器
    • 使用舉例:

      • 只讀設置
      • 函數式編程:過濾器
      • 函數式編程:轉換
      • 組合式函數編程
      • 加入約束:非空、長度驗證
      • 集合操做:交集、差集、並集
      • Multiset:無序可重複
      • Multimapkey能夠重複
      • BiMap:雙向Map(bidirectioal Map)鍵與值不能重複
      • 雙鍵的Map–>Table–>rowKey+columnKey+value
    • 示例:

      import java.text.SimpleDateFormat;
      import java.util.*;
      
      import com.google.common.base.Function;
      import com.google.common.base.Functions;
      import com.google.common.collect.*;
      import com.google.common.collect.Table.Cell;
      import org.junit.Test;
      
      /** * @author xiao兒 * @date 2019/9/3 10:01 * @Description GuavaDemo */
      public class GuavaDemo {
          /** * 設置只讀 */
          @Test
          public void testGuava1() {
              System.out.println("test Guava1");
              // List<String> list = Arrays.asList("Tom", "Lily", "Bin", "Jack");
              // list.add("Job");
              List<String> list = new ArrayList<>();
              list.add("Jack");
              list.add("Tom");
              list.add("Lily");
              list.add("Bin");
              // List<String> readList = Collections.unmodifiableList(list);
              // readList.add("Vince");
      
              // ImmutableList<String> iList = ImmutableList.of("Jack", "Lily", "Tom", "Bin");
              // iList.add("Job");
          }
      
          /** * 過濾器 */
          @Test
          public void testGuava2() {
              List<String> list = Lists.newArrayList("Java", "H5", "JavaScript", "Python", "PHP");
              Collection<String> result = Collections2.filter(list, (e) -> e.startsWith("J"));
              result.forEach((value) -> System.out.println(value));
          }
      
          /** * 轉換 */
          @Test
          public void testGuava3() {
              Set<Long> timeSet = Sets.newHashSet(20121212L, 20190901L, 20180808L);
              Collection<String> timeCollection = Collections2.transform(timeSet, (e) -> new SimpleDateFormat("yyyy-MM-dd").format(e));
              timeCollection.forEach(System.out::println);
          }
      
          /** * 組合式函數編程 */
          @Test
          public void testGuava4() {
              List<String> list = Lists.newArrayList("Java", "H5", "JavaScript", "Python", "PHP");
              Function<String, String> function = new Function<String, String>() {
                  @Override
                  public String apply(String input) {
                      return input.length() > 4 ? input.substring(0, 4) : input;
                  }
              };
              Function<String, String> function1 = new Function<String, String>() {
                  @Override
                  public String apply(String input) {
                      return input.toUpperCase();
                  }
              };
      
              Function<String, String> function2 = Functions.compose(function, function1);
              Collection<String> collection = Collections2.transform(list, function2);
              collection.forEach(System.out::println);
          }
      
          /** * 加入約束:非空、長度驗證 */
          @Test
          public void testGuava5() {
              // Set<String> set = Sets.newHashSet();
              // 14版本可用
              // Constraint<String> constraint = new Constraint<>() {
              // @Override
              // public String checkElement(String element) {
              //
              // }
              // };
              // Preconditions.checkArgument(expression);
              // Preconditions.checkNotNull(reference);
          }
      
          /** * 集合操做:交集、差集、並集 */
          @Test
          public void testGuava6() {
              Set<Integer> set = Sets.newHashSet(1, 2, 3);
              Set<Integer> set1 = Sets.newHashSet(3, 4, 5);
              // 交集
              Sets.SetView<Integer> view = Sets.intersection(set, set1);
              view.forEach(System.out::println);
              System.out.println("----------------");
              // 差集
              Sets.SetView<Integer> view1 = Sets.difference(set, set1);
              view1.forEach(System.out::println);
              System.out.println("----------------");
              // 並集
              Sets.SetView<Integer> view2 = Sets.union(set, set1);
              view2.forEach(System.out::println);
          }
      
          /** * Multiset:無序可重複 */
          @Test
          public void testGuava7() {
              String s = "good good study day day up";
              String[] strings = s.split(" ");
              HashMultiset<String> hashSet = HashMultiset.create();
              for (String str : strings) {
                  hashSet.add(str);
              }
              Set<String> set = hashSet.elementSet();
              for (String str : set) {
                  System.out.println(str + ":" + hashSet.count(str));
              }
          }
      
          /** * Multimap:key能夠重複 */
          @Test
          public void testGuava8() {
              Map<String, String> map = new HashMap<>();
              map.put("Java從入門到放棄", "Bin");
              map.put("Android從入門到放棄", "Bin");
              map.put("PHP從入門到放棄", "Jack");
              map.put("笑看人生", "Job");
      
              Multimap<String, String> multimap = ArrayListMultimap.create();
              Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
              while (iterator.hasNext()) {
                  Map.Entry<String, String> entry = iterator.next();
                  multimap.put(entry.getValue(), entry.getKey());
              }
      
              Set<String> keySet = multimap.keySet();
              for (String key : keySet) {
                  Collection<String> value = multimap.get(key);
                  System.out.println(key + "->" + value);
              }
          }
      
          /** * BiMap:雙向Map(bidirectional Map)鍵與值不能重複 */
          @Test
          public void testGuave9() {
              BiMap<String, String> map = HashBiMap.create();
              map.put("finally_test", "1820232384233");
              map.put("bin_test", "23234342343");
              map.put("tom_test", "4324334234234");
              String name = map.inverse().get("4324334234234");
              System.out.println(name);
      
              System.out.println(map.inverse().inverse() == map);
          }
      
          /** * 雙鍵的Map-->Table-->rowKey + columnKey + value */
          @Test
          public void testGuava10() {
          	Table<String, String, Integer> table = HashBasedTable.create();
          	table.put("Jack", "Java", 80);
          	table.put("Tom", "Python", 90);
          	table.put("Bin", "PHP", 70);
          	table.put("Lily", "JavaScript", 30);
      
          	Set<Cell<String, String, Integer>> cells = table.cellSet();
          	for (Cell c : cells) {
      			System.out.println(c.getRowKey() + "-" + c.getColumnKey() + "-" + c.getValue());
      		}
          }
      }
    • 注意:guava開源包下載地址:guava下載

相關文章
相關標籤/搜索