天天看點

c++ map 修改value_Set、Map實作類的簡單介紹

c++ map 修改value_Set、Map實作類的簡單介紹

Collection是Java集合架構的的頂層接口,裡面的子接口主要有Set和List兩大類。

今天簡單的總結一下,List接口下的實作類HashSet、TreeSet和LinkHashSet。

Map接口下的實作類有HashMap、LinkedHashMap、TreeMap

HashSet:

底層資料結構是為哈希表,他的工作原理如下圖所示

c++ map 修改value_Set、Map實作類的簡單介紹

它添加元素時離不開hashCode和equals方法,通過這兩種方法進行去重和散列。上面的元素為Integer類型,Integer類型對象的hashCode就是數值的本身。存到HashSet的中的元素為無序元素。如果要把自定義對象寫入HashSet裡,就要對equals方法和hashCode方法進行重寫。優點:添加、删除、查詢效率高。缺點:無序。

LinkHashSet:

底層資料結構為哈希表+連結清單。

哈希表就如上圖所示一樣,用于散列元素并去重。連結清單用于維持添加順序。如果要添加自定義對象也一樣需要重寫equals方法和hashCode方法。

TreeSet:

底層資料結構為二叉樹。存儲的資料按照一定的規則存儲。存儲規則讓資料表現出自然順序。我們随意存儲1,2,3,30,10,4這幾個數進去,畫圖了解可以得到下圖的樣式:

c++ map 修改value_Set、Map實作類的簡單介紹

添加新元素的步驟:

[1] 如果集合無元素,t直接加入;如果集合有元素,t和根節點比較;

[2] 如果t小于根節點;把t放到根節點的左子樹上;重複1-3步驟

[3] t大于根節點;把t放到根節點的右子樹上;重複1-3步驟

輸出時按照一定的規則:左子樹->根節點->右子樹

向TreeSet中添加元素時,一定要提供

比較政策,

否則會出現ClassCastException。即類型轉換異常。當一個自定義對象作為元素要添加到TreeSet中,提供的比較政策可以用到内部比較器或者外部比較器。

内部比較器:自定義對象實作Comparable并實作compareTo方法時,通過指定具體的比較政策。比如說學生作為元素要添加到TreeSet中,Student類中實作Comparable接口:

public class Student implements Comparable<Student>{
 private String id;
 private String name;
 private int age;
 
 // 。。。
 
 @Override
 public String toString() {
  return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
 }
 
 @Override
 public int compareTo(Student o) {
  if(this.getAge()<o.getAge()) {
   return -1;
  }else if(this.getAge() == o.getAge()) {
   return 0;
  }else {
   return 1;
  }
 }
 
}
           

這裡用學生的年齡作為比較政策。

比較政策一般目前對象寫在前面,待比較對象也在後面,比較結果預設升序

return this.getAge() - o.getAge() ;
           

如果想要降序,改變兩個比較對象的位置即可。

多種比較因素:

@Override
 public int compareTo(Student o) {
  /*if(this.getAge()<o.getAge()) {
   return -1;
  }else if(this.getAge() == o.getAge()) {
   return 0;
  }else {
   return 1;
  }*/
  
  // return  this.getAge() - o.getAge() ;
  
  if(this.getAge()<o.getAge()) {
   return -1;
  }else if(this.getAge() == o.getAge()) {
   return this.getName().compareTo(o.getName());
  }else {
   return 1;
  }
 }
           

像如果年齡相同,我們可以比較學生的姓名。

外部比較器:當實際開發過程中不知道添加元素的源代碼、無權修改别人的代碼,此時可以使用外部比較器。

Comparator 位于java.util包中,定義了compare(o1,o2) 用于提供外部比較政策。

TreeSet接受一個指定比較政策的構造方法,這些比較政策的實作類必須實作Comparator

接口。比如說我們用匿名内部類進行優化:

public class Test02 {
 public static void main(String[] args) {
  
  TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {
 
   @Override
   public int compare(String o1, String o2) {
    return o1.length() - o2.length();
   }
   
  });
  
  set2.add("banana");
  set2.add("coco");
  set2.add("apple");
  
  set2.add("apple");
  System.out.println(set2);
  
 }
}
           

Map接口

Map接口稱為鍵值對集合或者映射集合,其中的元素(entry)是以鍵值對(key-value)的形式存在。

Map 容器接口中提供了增、删、改、查的方式對集合進行操作。

Map接口中都是通過key來操作鍵值對,一般key是已知。通過key擷取value。

map的接口的周遊

通過keySet() 傳回map中鍵的set集合。下圖是在API中查到的。

c++ map 修改value_Set、Map實作類的簡單介紹
public static void main(String[] args) {
 
  Map<String, String> map = new HashMap<String,String>();
  
  map.put("B", "banana");
  map.put("A", "apple");
  map.put("C", "coco");
  // map無序
  // 可以根據key的自然順序 讓map有序  => 一般用string作為key
  System.out.println(map);
  
  
  // 周遊
  Set<String> keys = map.keySet();
  for (String key : keys) {
   System.out.println(key+"=>"+map.get(key));
  }
  
  Iterator<String> it = keys.iterator();
  while(it.hasNext()) {
   String key = it.next();
   System.out.println(key+"=>"+map.get(key));
  }
 }
           

map中以鍵值對作為元素,鍵值對在map中稱為entry,entrySet傳回鍵值對的set集合。

c++ map 修改value_Set、Map實作類的簡單介紹
public static void main(String[] args) {
 
  Map<String, String> map = new HashMap<String,String>();
  
  map.put("B", "banana");
  map.put("A", "apple");
  map.put("C", "coco");
  // map無序
  // 可以根據key的自然順序 讓map有序  => 一般用string作為key
  System.out.println(map);
  
  // entrySet
  Set<Entry<String, String>> entrySet = map.entrySet();
  for (Entry<String, String> entry : entrySet) {
   System.out.println(entry.getKey()+"=>"+entry.getValue());
  }
  
  Iterator<Entry<String, String>> it2 = entrySet.iterator();
  while(it2.hasNext()) {
   Entry<String, String> entry = it2.next();
   System.out.println(entry.getKey()+"=>"+entry.getValue());
  }
 }
           

HashMap

HashMap 是Map的實作類,key以HashSet存儲。

public static void main(String[] args) {

  HashMap<Student, Object> map = new HashMap<Student,Object>();
  
  ArrayList<String> list1 = new ArrayList<String>();
  list1.add("alex");
  list1.add("alice");
  list1.add("allen");
  Student s1 = new Student("001", "大狗", 20);
  map.put(s1, list1);
  
  
  ArrayList<String> list2 = new ArrayList<String>();
  list2.add("ben");
  list2.add("bill");
  Student s2 = new Student("001", "大狗", 20);
  // 修改
  map.put(s2, list2);
  System.out.println(map);
  
 }
           

以上代碼如果要實作修改的功能,要對Student的類進行hashcode方法和equals方法進行重寫。

[1] 向HashMap中存儲元素時,key一定要實作hashCode和equals

[2] 一般建議使用String作為Map接口的key。

LinkedHashMap

LinkedHashMap是Map接口的實作類,key以LinkedHashSet存儲。

哈希表散列key,連結清單維持key的添加順序。

public static void main(String[] args) {

  HashMap<Student, Object> map = new HashMap<Student,Object>();
  
  ArrayList<String> list1 = new ArrayList<String>();
  list1.add("alex");
  list1.add("alice");
  list1.add("allen");
  Student s1 = new Student("001", "大狗", 20);
  map.put(s1, list1);
  
  
  ArrayList<String> list2 = new ArrayList<String>();
  list2.add("ben");
  list2.add("bill");
  Student s2 = new Student("001", "大狗", 20);
  // 修改
  map.put(s2, list2);
  System.out.println(map);
  
 }
           

以上代碼如果要實作修改的功能,要對Student的類進行hashcode方法和equals方法進行重寫。

TreeMap

TreeMap是Map的實作類,key以TreeSet存儲。

public static void main(String[] args) {
  
  
  /*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {
 
   @Override
   public int compare(String o1, String o2) {
    return o1.length() - o2.length();
   }
  });
  
  ArrayList<String> list2 = new ArrayList<String>();
  list2.add("ben");
  list2.add("bill");
  map.put("Aa", list2);
  
  ArrayList<String> list1 = new ArrayList<String>();
  list1.add("alex");
  list1.add("alice");
  list1.add("allen");
  map.put("B", list1);
  
  System.out.println(map);*/
  
  
  
  TreeMap<Student, Object> map = new TreeMap<Student,Object>(new Comparator<Student>() {
 
   @Override
   public int compare(Student o1, Student o2) {
    return o1.getAge() - o2.getAge();
   }
  });
  
  ArrayList<String> list1 = new ArrayList<String>();
  list1.add("alex");
  list1.add("alice");
  list1.add("allen");
  Student s1 = new Student("001", "大狗", 20);
  map.put(s1, list1);
  
  
  ArrayList<String> list2 = new ArrayList<String>();
  list2.add("ben");
  list2.add("bill");
  Student s2 = new Student("001", "2狗", 20);
  // 修改
  map.put(s2, list2);
  System.out.println(map);
  
 }
           

這裡用外部比較器Comparator匿名内部類,添加比較政策。

繼續閱讀