<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java的基本使用之集合

      1、集合

       在Java中,如果一個Java對象可以在內部持有若干其他 Java 對象,并對外提供訪問接口,我們把這種Java對象稱為集合。很顯然,Java 的數(shù)組可以看作是一種集合。

      在Java中數(shù)組有如下限制:

      • 數(shù)組初始化后大小不可變;
      • 數(shù)組只能按索引順序存取。

      因此,我們需要各種不同類型的集合類來處理不同的數(shù)據(jù),例如:

      • 可變大小的順序鏈表;
      • 保證無重復元素的集合.....

      最常用的集合有:ArrayList,HashSet,HashMap,Array(數(shù)組)。

      Java標準庫自帶的java.util包提供了集合類:Collection ,它是除 Map 外所有其他集合類的根接口。Java的java.util包主要提供了以下三種類型的集合:

      • List:一種有序列表的集合,例如,按索引排列的StudentList
      • Set:一種保證沒有重復元素的集合,例如,所有無重復名稱的StudentSet
      • Map:一種通過鍵值(key-value)查找的映射表集合,例如,根據(jù)Studentname查找對應StudentMap

      1.1、集合的特點

      java 中的集合可以存放不同類型、不限數(shù)量的數(shù)據(jù)類型(可以通過泛型來限制只可以存入某種類型的數(shù)據(jù))。Java 中的集合只能存放對象,比如你把一個 int 類型的數(shù)據(jù) 1 放入集合,其實它是自動轉換成 Integer 類后放入的。

      Java集合的其他特點:

      1. 實現(xiàn)了接口和實現(xiàn)類相分離,例如,有序表的接口是List,具體的實現(xiàn)類有ArrayListLinkedList等,
      2. 支持泛型,我們可以限制在一個集合中只能放入同一種數(shù)據(jù)類型的元素,例如:List<String> list = new ArrayList<>(); // 只能放入String類型
      3. Java訪問集合總是通過統(tǒng)一的方式——迭代器(Iterator)來實現(xiàn),通過迭代器訪問無需知道集合內部的元素的存儲方式

       

      2、List 集合(有序可重復,可變長度數(shù)組)

      List 集合是一種有序列表,它的行為和數(shù)組幾乎完全相同:List 內部按照放入元素的先后順序存放,每個元素都可以通過索引確定自己的位置,List的索引和數(shù)組一樣,從0開始。List 集合的大小是可變的。

      List 代表一個元素有序且可重復的集合,集合中的每個元素都有其對應的順序索引。

      List 允許使用重復元素,可以通過索引來訪問指定位置的集合元素。List 默認按元素的添加順序設置元素的索引

       

      2.1、ArrayList 有序列表

      在實際應用中,需要增刪元素的有序列表,我們使用最多的是ArrayList。實際上,ArrayList在內部是使用數(shù)組來存儲所有元素的。

       

      2.2、LinkedList 有序列表

       ArrayList 通過數(shù)組的方式實現(xiàn)了 List 接口,LinkedList通過“鏈表”的方式實現(xiàn)了List接口,在LinkedList中,它的內部每個元素都指向下一個元素:

       

       

      2.3、ArryList 和 LinkedList 的對比

      ArrayList 集合的底層數(shù)據(jù)結構是數(shù)組,它查詢快,增刪慢!線程不安全,但是效率高!

      LinkedList 集合的底層數(shù)據(jù)結構是鏈表,它查詢慢,但是增刪快!線程不安全,但是效率高!

      在各種Lists中,最好的做法是以 ArrayList 作為缺省選擇。當插入、刪除頻繁時,可以使用 LinkedList()

       

      2.4、List 集合的幾個主要接口方法

      List<E>接口的幾個主要的接口方法:

      • 在末尾添加一個元素:void add(E e)
      • 在指定索引添加一個元素:void add(int index, E e)
      • 刪除指定索引的元素:int remove(int index)
      • 刪除某個元素:int remove(Object e)
      • 獲取指定索引的元素:E get(int index)
      • 獲取鏈表大小(包含元素的個數(shù)):int size()
      • 獲取元素第一次出現(xiàn)的位置:int indexOf(E e)
      • 修改指定位置的元素:E set(int index, E e )

      示例:

      List<String> list = new ArrayList<>();
      list.add("apple");  
      list.add("null");    // 允許添加 null
      list.add("apple");   // 允許重復添加元素
      System.out.println(list.size());  //size: 3
      
      String str = list.get(0); // "apple"

       

      創(chuàng)建 List:

      除了使用ArrayListLinkedList,我們還可以通過List接口提供的of()方法,根據(jù)給定元素快速創(chuàng)建List

      List<Integer> list = List.of(1, 2, 5);

      但是List.of()方法不接受null值,如果傳入null,會拋出NullPointerException異常。

       

      2.5、遍歷 List 集合

      2.5.1、for 循環(huán)遍歷(不推薦使用)

      和數(shù)組類型一樣,我們要遍歷一個List,完全可以用for循環(huán)根據(jù)索引配合get(int)方法遍歷:

      List<String> list = List.of("apple", "pear", "banana");
      for (int i=0; i<list.size(); i++) {
               String s = list.get(i);
               System.out.println(s);
      }

      但這種方式并不推薦,一是代碼復雜,二是因為get(int)方法只有ArrayList的實現(xiàn)是高效的,換成LinkedList后,索引越大,訪問速度越慢。

       

      2.5.2、迭代器 Iterator 遍歷(推薦使用)

      for 循環(huán)使用迭代器

      我們應該始終堅持使用迭代器Iterator來訪問List,Iterator本身也是一個對象,但它是由List的實例調用iterator()方法的時候創(chuàng)建的。Iterator對象知道如何遍歷一個List,并且不同的List類型,返回的Iterator對象實現(xiàn)也是不同的,但總是具有最高的訪問效率。

      List<String> list = List.of("apple", "pear", "banana");
      for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
               String s = it.next();
               System.out.println(s);
      }

       

      for each 循環(huán)使用迭代器

      通過Iterator遍歷List永遠是最高效的方式。由于Iterator遍歷非常常用,為了簡潔代碼,在 Java 中也支持通過 for each 循環(huán)來使用Iterator遍歷

      public class Main {
          public static void main(String[] args) {
              List<String> list = List.of("apple", "pear", "banana");
              for (String s : list) {
                  System.out.println(s);
              }
          }
      }

      實際上,只要實現(xiàn)了Iterable接口的集合類都可以直接用for each循環(huán)來遍歷,Java編譯器本身并不知道如何遍歷集合對象,但它會自動把for each循環(huán)變成Iterator的調用,原因就在于Iterable接口定義了一個Iterator<E> iterator()方法,強迫集合類必須返回一個Iterator實例。

       

      2.6、編寫equals()方法以滿足contains()和indexOf()方法的使用

      要正確使用Listcontains()indexOf()方法,放入的實例必須正確覆寫equals()方法。

      List提供了boolean contains(Object o)方法來判斷List是否包含某個指定元素。此外,int indexOf(Object o)方法可以返回某個元素的索引,如果元素不存在,就返回-1

      List<String> list = List.of("A", "B", "C");
      System.out.println(list.contains("C")); // true
      System.out.println(list.contains("X")); // false
      
      System.out.println(list.indexOf("C")); // 2
      System.out.println(list.indexOf("X")); // -1

      List內部并不是通過==判斷兩個元素是否相等,而是使用equals()方法判斷兩個元素是否相等。因此,要正確使用Listcontains()indexOf()這些方法,放入的實例必須正確覆寫equals()方法,否則,放進去的實例,查找不到。我們之所以能正常放入StringInteger這些對象,是因為Java標準庫定義的這些類已經正確實現(xiàn)了equals()方法。

      代碼示例:

      //下面的list集合中雖然放入了new Person("Bob"),但是用另一個new Person("Bob")查詢不到,原因就是Person類沒有覆寫equals()方法。
      public class Main {
          public static void main(String[] args) {
              List<Person> list = List.of(
                  new Person("Bob")
              );
              System.out.println(list.contains(new Person("Bob"))); // false
          }
      }
      
      class Person {
          String name;
          public Person(String name) {
              this.name = name;
          }
      }

      2.6.1、如何覆寫equals方法

      equals()方法的正確編寫方法:

      1. 先確定實例“相等”的邏輯,即哪些字段相等,就認為實例相等
      2. instanceof判斷傳入的待比較的Object是不是當前類型,如果是,繼續(xù)比較,否則,返回false
      3. 對引用類型用Objects.equals()比較,對基本類型直接用==比較。使用Objects.equals()比較兩個引用類型是否相等可以省去判斷null的麻煩。兩個引用類型都是null時它們也是相等的。

      首先,我們要定義“相等”的邏輯含義。比如對于Person類,如果name相等,并且age相等,我們就認為兩個Person實例相等。

      public boolean equals(Object o) {
          if (o instanceof Person) {
              Person p = (Person) o;
              return Objects.equals(this.name, p.name) && this.age == p.age;
          }
          return false;
      }

      如果不調用Listcontains()indexOf()這些方法,那么放入的元素就不需要實現(xiàn)equals()方法

       

      3、Map 集合(key--value,類似于對象)

      Map 集合是一種通過鍵值(key-value)查找的映射表集合,map 集合的作用就是能高效地通過 key 來查找對應的 value 值,提高查找效率。

      Map 中不允許存在重復的 key,如果放入相同的key,只會把原有的 key-value 對應的 value 給替換掉。

      和 List 類似,Map 也是一個接口,最常用的實現(xiàn)類是 HashMap。

      3.1、關于Map集合的方法

      put(k, v) 和 get(k) 方法存取元素

      通過 put(key, value) 方法來放入值,如果 key 已經存在,該方法返回已經存在的 key 對應的 value 值,并且后放入的 value 將會替代掉舊的 value。如果 key 不存在,該方法返回 null。

      通過 get(key) 方法來取值,如果 key 在 map 集合中不存在,將返回 null 。

      public class Main {
          public static void main(String[] args) {
              Student s = new Student("Xiao Ming", 99);
              Map<String, Student> map = new HashMap<>();
              map.put("Xiao Ming", s);                // 插入值,將"Xiao Ming"和Student實例映射并關聯(lián)
              Student target = map.get("Xiao Ming");  // 取值,通過key查找并返回映射的Student實例
              System.out.println(target == s);        // true,同一個實例
              Student another = map.get("Bob");       // 未找到返回 null
          }
      }
      
      class Student {
          public String name;
          public int score;
          public Student(String name, int score) {
              this.name = name;
              this.score = score;
          }
      }

      Map 集合可以重復放入key-value,但是一個key只能關聯(lián)一個value,后面放入的value會替代掉前面的value。如果放入的key已經存在,put()方法會返回被刪除的舊的value,否則,返回null

      在一個Map中,雖然key不能重復,但value是可以重復的

       

      查詢key是否存在(containsKey(k)):如果只是想查詢某個key是否存在,可以調用boolean containsKey(K key)方法。

      查詢value是否存在(containsValue(v))

      根據(jù)key值移除元素(mapObj.remove(k))

       

      3.2、遍歷 Map

      MapList不同,Map存儲的是key-value的映射關系,并且,它不保證順序。在遍歷的時候,遍歷的順序既不一定是put()時放入的key的順序,也不一定是key的排序順序。遍歷的時候,每個key會保證被遍歷一次且僅遍歷一次,但順序完全沒有保證,甚至對于不同的JDK版本,相同的代碼遍歷的輸出順序都是不同的!

      HashMap 內部的 key 是無序的,TreeMap 的 key 是有序的。

      3.2.1、遍歷所有的key(keySet())

      要遍歷 Map 集合的 key 可以使用 for each 循環(huán)來遍歷 Map 實例的 keySet() 方法返回的 Set 集合,該 Set 集合包含不重復的key的集合:

      Map<String, Integer> map = new HashMap<>();
      map.put("apple", 123);
      map.put("pear", 456);
      map.put("banana", 789); 
      for (String key : map.keySet()) {      //keySet()方法返回一個不包含重復key的set集合
               Integer value = map.get(key);
               System.out.println(key + " = " + value);
      }

       

       3.2.2、直接遍歷key--value(entrySet())

      同時遍歷keyvalue可以使用for each循環(huán)遍歷Map對象的entrySet()集合,它包含每一個key-value映射:

      Map<String, Integer> map = new HashMap<>();
      map.put("apple", 123);
      map.put("pear", 456);
      map.put("banana", 789);
      for (Map.Entry<String, Integer> entry : map.entrySet()) {
               String key = entry.getKey();
               Integer value = entry.getValue();
               System.out.println(key + " = " + value);
      }

       

      3.3、覆寫equals()和hashcode()方法

      正確使用 Map 必須保證:

      1. 作為key的對象必須正確覆寫equals()方法,相等的兩個key實例調用 eauals() 必須返回 true,不同的key返回false

      2. 作為key的對象還必須正確覆寫hashCode()方法,且hashCode()方法要嚴格遵循以下規(guī)范:如果兩個對象相等,則兩個對象的hashCode()必須相等;如果兩個對象不相等,則兩個對象的hashCode()不要相等。

      我們經常使用String作為key,因為String已經正確覆寫了equals()和hashCode()方法。

      3.3.1、覆寫equals()方法

      要想保證通過內容相同但不一定是同一個對象的 key 獲取到同一個 value 值,必須得保證作為 key 的對象已經正確地覆寫了 equals() 方法。

      通過不是同一個對象,但是內容相同的 key 實例可以取到同一個 value 值,這是因為 Map 內部對 key 做比較是通過 equals 方法實現(xiàn)的,這一點和List查找元素需要正確覆寫equals()是一樣的,即正確使用Map必須保證:作為key的對象必須正確覆寫equals()方法。 

      我們經常使用String作為key,因為String已經正確覆寫了equals()方法。但如果我們放入的key是一個自己寫的類,就必須保證正確覆寫了equals()方法。

       

      3.3.2、覆寫hashcode()方法

      Map 集合是通過 key 計算出 value 存儲的索引的,計算方式是調用了 key 對象的 hashcode() 方法,它返回一個 int 整數(shù),HashMap 正是通過這個方法直接定位key對應的value的索引,繼而直接返回value

      在正確實現(xiàn)equals()的基礎上,我們還需要正確實現(xiàn)hashCode(),代碼示例:

      public class Person {
          String firstName;
          String lastName;
          int age;
      
          @Override
          int hashCode() {
              int h = 0;
              h = 31 * h + firstName.hashCode();
              h = 31 * h + lastName.hashCode();
              h = 31 * h + age;
              return h;
          }
      
         //為了避免firstName或lastName為null,代碼拋NullPointerException異常,hashCode方法可以這么寫
         @Override
         int hashCode() {
              return Objects.hash(firstName, lastName, age);
         }
      }

      equals()方法中用到的用于比較的每一個字段,都必須在hashCode()中用于計算;equals()中沒有使用到的字段,絕不可放在hashCode()中計算。

       

      3.4、TreeMap(元素有序)

      HashMap 內部的 key 是無序的,還有一種Map,它在內部會對Key進行排序,這種Map就是SortedMap。注意到SortedMap是接口,它的實現(xiàn)類是TreeMapTreeMap不使用equals()hashCode(),所以不需要覆寫equals和hashCode方法。

       

       

      SortedMap保證遍歷時以Key的順序來進行排序。例如,放入的Key是"apple""pear""orange",遍歷的順序一定是"apple""orange""pear",因為String默認按字母排序:

      使用TreeMap時,放入的Key必須實現(xiàn)Comparable接口。StringInteger這些類已經實現(xiàn)了Comparable接口,因此可以直接作為Key使用。

      如果作為Key的class沒有實現(xiàn)Comparable接口,那么,必須在創(chuàng)建TreeMap時傳入Comparator即指定一個自定義排序算法:

      import java.util.*;
      public class Main {
          public static void main(String[] args) {
              Map<Person, Integer> map = new TreeMap<>(new Comparator<Person>() {   //在創(chuàng)建 TreeMap 時傳入一個排序算法
                  public int compare(Person p1, Person p2) {
                      return p1.name.compareTo(p2.name);
                  }
              });
              map.put(new Person("Tom"), 1);
              map.put(new Person("Bob"), 2);
              map.put(new Person("Lily"), 3);
              for (Person key : map.keySet()) {
                  System.out.println(key);   // {Person: Bob}, {Person: Lily}, {Person: Tom}
              }
              System.out.println(map.get(new Person("Bob"))); // 2
          }
      }
      
      class Person {
          public String name;
          Person(String name) {
              this.name = name;
          }
          public String toString() {
              return "{Person: " + name + "}";
          }
      }
      
      //比較的值是數(shù)字
       Map<Student, Integer> map = new TreeMap<>(new Comparator<Student>() {
            public int compare(Student p1, Student p2) {
                if (p1.score == p2.score) {
                     return 0;
                }
                return p1.score > p2.score ? -1 : 1;
                //或者可以直接借助Integer.compare(int, int)也可以返回正確的比較結果,就不用寫上面這么多判斷了
           }
      });

       

      4、Set 集合(元素不重復)

      Set用于存儲不重復的元素集合,它主要提供以下幾個方法:

      • 添加元素:boolean add(E e)
      • 刪除元素:boolean remove(Object e)
      • 判斷是否包含元素:boolean contains(Object e)

      代碼示例:

      Set<String> set = new HashSet<>();
      System.out.println(set.add("abc")); // true
      System.out.println(set.add("abc")); // false,添加失敗,因為元素已存在,不可添加重復元素
      System.out.println(set.contains("abc")); // true,元素存在
      System.out.println(set.contains("xyz")); // false,元素不存在
      System.out.println(set.remove("hello")); // false,刪除失敗,因為元素不存在
      System.out.println(set.size()); // 1,一共1個元素

      放入Set的元素和Map的key類似,都要正確實現(xiàn) equals() 和 hashCode()方法,否則該元素無法正確地放入 Set。

      最常用的Set實現(xiàn)類是HashSet,實際上,HashSet僅僅是對HashMap的一個簡單封裝。

      繼承關系:

       

      4.1、HashSet

      Set接口并不保證有序,而SortedSet接口則保證元素是有序的。HashSet 是無序的,它實現(xiàn)了Set接口,但沒有實現(xiàn)SortedSet接口;

      當向一個 HashSet 集合存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的 hashCode 值,然后根據(jù) hashCode值決定該元素在 HashSet 中的存儲位置。如果兩個元素的 equals 方法返回 true,但它們的 hashCode() 返回值不相等,那這兩個元素仍然可以添加成功,hashSet 會將它們存儲在不同的位置。

      HashSet 集合判斷兩個元素相等的標準:兩個對象通過 equals() 方法比較返回 true,并且兩個對象的 hashCode() 方法返回值也相等。

      如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。

       

      HashSet 是無序的,可以存放 null。

      public class Main {
          public static void main(String[] args) {
              Set<String> set = new HashSet<>();
              set.add("apple");
              set.add("banana");
              set.add("pear");
              set.add("orange");
              for (String s : set) {
                  System.out.println(s);   //亂序輸出 banana apple pear ...
              }
          }
      }

       

      4.2、TreeSet

      TreeSet 是有序的,因為它實現(xiàn)了SortedSet接口。在遍歷TreeSet時,輸出就是有序的,順序按插入的元素ASCll碼排序。

      public class Main {
          public static void main(String[] args) {
              Set<String> set = new TreeSet<>();
              set.add("apple");
              set.add("banana");
              set.add("pear");
              set.add("orange");
              for (String s : set) {
                  System.out.println(s);   //輸出apple  banana  orange  pear
              }
          }
      }

      使用TreeSet和使用TreeMap的要求一樣,添加的元素必須正確實現(xiàn)Comparable接口,如果沒有實現(xiàn)Comparable接口,那么創(chuàng)建TreeSet時必須傳入一個Comparator對象。

       

      5、迭代器的使用

      迭代器是一種設計模式,它是一個對象,它可以遍歷并選擇序列中的對象,而開發(fā)人員不需要了解該序列的底層結構。迭代器通常被稱為“輕量級”對象,因為創(chuàng)建它的代價小。

      Java中的Iterator功能比較簡單,并且只能單向移動:

      1. 使用 iterator() 方法會返回一個 Iterator 對象。第一次調用 Iterator 對象的 next() 方法時,它返回序列的第一個元素。(注意,iterator() 方法是 java.lang.Iterable接口,被 Collection 繼承)
      2. 使用 next() 獲得序列中的下一個元素
      3. 使用 hasNext() 檢查序列中是否還有元素
      4. 使用 remove() 將迭代器新返回的元素刪除

      Iterator 是Java迭代器最簡單的實現(xiàn),為 List 設計的 ListIterator 具有更多的功能,它可以從兩個方向遍歷List,也可以從 List 中插入和刪除元素。

      list l = new ArrayList();
      l.add("aa");
      l.add("bb");
      for (Iterator iter = l.iterator(); iter.hasNext();) {
        String str = (String)iter.next();
        System.out.println(str);
      } 
      
      /*迭代器用于 while 循環(huán)遍歷
          Iterator iter = l.iterator();
          while(iter.hasNext()){
              String str = (String) iter.next();
              System.out.println(str);
          }
      */
      
      /*迭代器用于 for each 循環(huán)遍歷
          for(Object obj : iter) {
              System.out.println(obj);
          }
      */

       

      posted @ 2020-01-01 12:31  wenxuehai  閱讀(353)  評論(0)    收藏  舉報
      //右下角添加目錄
      主站蜘蛛池模板: 亚洲伊人久久综合影院| 成人网站免费观看永久视频下载| 亚洲av一本二本三本| 欧美不卡无线在线一二三区观 | 国产精品入口麻豆| 人妻少妇精品视频二区| 一区二区在线欧美日韩中文| 洞口县| 97亚洲熟妇自偷自拍另类图片| 人妻va精品va欧美va| 亚洲综合中文字幕首页| 无遮无挡爽爽免费视频| 国产高清吹潮免费视频| 久久国产免费观看精品3| 99精品久久毛片a片| 国产日女人视频在线观看| 久久中文字幕av第二页| 亚洲av无码乱码在线观看牲色| 不卡av电影在线| 日韩乱码卡一卡2卡三卡四| 国产一区二区三区18禁| 一本色道久久加勒比综合 | 成人无码午夜在线观看| 骚虎视频在线观看| 五月婷婷开心中文字幕| 欧洲亚洲精品免费二区| 成人精品网一区二区三区| 毛片在线看免费| 国产日韩av二区三区| 亚洲日本乱码熟妇色精品| 日韩国产亚洲一区二区三区| av无码精品一区二区三区四区 | 精品亚洲没码中文字幕| 国产亚洲精品第一综合另类无码无遮挡又大又爽又黄的视频 | 精品精品亚洲高清a毛片| 国内少妇偷人精品免费| 别揉我奶头~嗯~啊~的视频| 中文无码乱人伦中文视频在线| 亚洲区综合区小说区激情区| 国产精品国产三级国快看| 欧美xxxx做受欧美.88|