JAVA -- Set and Map

Posted by ATS16805 on Sun, 16 Jan 2022 16:23:17 +0100

Set

1. Overview and characteristics

  • A collection that does not contain duplicate elements. More specifically, set does not contain a set that satisfies e1 Equals (e2) has element pairs e1 and e2 and contains at most one null element.
  • The data in the Set collection is out of order (because the Set collection has no subscript)
  • Set does not allow duplicate data, null is allowed, but at most one
  • Because its data is non repeatable, Set is often used to de duplicate data

2.HashSet

  • This class (HashSet) implements the Set interface and is supported by a hash table (actually a HashMap instance).
  • The bottom layer of the HashSet is the hash table, which wraps the HashMap, which is equivalent to storing the data into the HashSet as K in the internal HashMap, where k is not allowed to be repeated and null is allowed
  • HashSet thread unsafe

3. Relevant tests

	package cn.tedu.list;
	
	import java.util.Arrays;
	import java.util.HashSet;
	import java.util.Iterator;
	import java.util.Set;
	
	//This class is used to test the Set interface
	public class TestSet {
	    public static void main(String[] args) {
	        //1. Create an object. The Set parent interface cannot directly create an object
	        Set<String> set = new HashSet<>();
	        /**
	         * Summary: the elements in the set are out of order,
	         * set Elements in the collection cannot be repeated
	         * set null can be stored in the collection, but only one is allowed
	         */
	        //2. Data storage
	        set.add("bullish");
	        set.add("Huhushengwei");
	        set.add("Huhushengwei");
	        set.add(null); //Store a null value into the collection
	        set.add("null"); //Store the string null into the collection
	        System.out.println(set); //[null, tiger, tiger, bull]
	
	        /*set.clear(); //Empty set set
	        System.out.println(set);*/
	        System.out.println(set.contains("bullish")); //true to judge whether the collection contains the specified element
	        System.out.println(set.equals("bullish")); //false to judge whether the collection is equal to the element
	        System.out.println(set.hashCode()); //1961052313, print the hash code value of the set
	        System.out.println(set.isEmpty()); //false to judge whether the collection is empty
	        System.out.println(set.remove(null)); //true to remove the specified element from the collection
	        System.out.println(set);
	        System.out.println(set.size()); //3. Print the number of elements in the set
	        Object[] array = set.toArray(); //Convert a set to an array
	        System.out.println(Arrays.toString(array)); //[huhushengwei, null, bullish]
	
	        //Iterate over collections using iterator
	        Iterator<String> it = set.iterator();
	        while (it.hasNext()){
	            System.out.println(it.next());
	        }
	    }
	}

4.HashSet weight removal

  • For general basic types of data, you can directly de duplicate them
  • If it is a custom object, such as the Student class object below, you must override the hashCode() and equals() methods to remove duplication
    • Student class
    package cn.tedu.list;
    
    import java.util.Objects;
    
    public class Student {
        private String name;
        private Integer age;
    
        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return Objects.equals(name, student.name) && Objects.equals(age, student.age);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }
    
    
    • Test class
    package cn.tedu.list;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class TestSet2 {
        public static void main(String[] args) {
            /**
             * Custom objects (such as Student class),
             * If you don't want to print the address value, override toString()
             * If you want to de duplicate, you need to add rewritten hashCode() and equals()
             */
            Set<Student> set2 = new HashSet<>();
            Student s1 = new Student("Zhang San",1);
            Student s2 = new Student("Li Si",2);
            Student s3 = new Student("Li Si",2);
            set2.add(s1);
            set2.add(s2);
            set2.add(s3);
            System.out.println(set2);
        }
    }
    
    

Map

5.Map overview and features

  • public interface Map<K,V>
  • An object that maps keys to values. A mapping cannot contain duplicate keys; Each key can be mapped to at most one value.
  • Type parameter: K - indicates the key maintained by this mapping; V - indicates the corresponding value maintained by this mapping
  • Note: Map has nothing to do with collection, not its sub interface. Collection is a collection of objects and Map is a collection of key value pairs.
  • The key in the Map cannot be repeated, but the value can be repeated. If there are multiple different values corresponding to the same key, the latter value will overwrite the previous value
  • The data stored in the Map is unordered

6. Common test methods

  • package cn.tedu.list;
    
    import java.util.*;
    
    //This class is used to test the Map interface
    public class TestMap {
        public static void main(String[] args) {
            //1. Create a Map object
            /**
             * Map The data in must comply with the mapping rules. Be sure to specify the K and V data types at the same time
             * The specific types of K and V depend on the specific business requirements
             */
            Map<Integer,String> map = new HashMap<>();
            //2. Store data into the map set. Note that the method is put(), and a pair of < K, V > values need to be stored
            map.put(9527,"Baigujing");
            map.put(9528,"Black bear essence");
            map.put(9529,"Carp essence");
            map.put(9530,"Yellow hair monster");
            /**
             * Map The data stored in is disordered data
             * Map The value in can be repeated,
             * However, the key in the Map cannot be repeated. If it is repeated, the following value will overwrite the previous value
             */
            map.put(9531,"Black bear essence");
            map.put(9529,"Daughter country King");
            System.out.println(map);
    
            //3. Conduct method test
            //map.clear();  // Empty collection
            System.out.println(map.hashCode()); //464950062, get the hash code value of the collection
            System.out.println(map.equals("Yellow hair monster")); //false to judge whether the "yellow hair monster" is equal to the collection object
            System.out.println(map.isEmpty()); //false to judge whether the collection is empty
            System.out.println(map.size()); //5. Get the number of elements in the collection
    
            System.out.println(map.containsKey(9527)); //true to judge whether the current map collection contains the specified key
            System.out.println(map.containsValue("Carp essence")); //false to judge whether the current map collection contains the specified value
    
            System.out.println(map.get(9530)); //The yellow hair monster obtains the corresponding value value according to the key value
    
            System.out.println(map.remove(9528)); //Black bear essence, delete the corresponding key value pair according to the specified key, and K and V are deleted
            System.out.println(map);
    
            //Take out all value s in the map Collection and put them into the Collection collection
            //The Type of Type in collection < Type > depends on the Type of value in the map
            Collection<String> values = map.values();
            System.out.println(values);
    
            //Take out all the key s in the map Set and put them into the Set set
            //The Type of Type in set < Type > depends on the Type of key in the map
            Set<Integer> keys = map.keySet();
            System.out.println(keys);
    
            System.out.println("******************************");
    
            //4. Iteration method 1 of map set
            /**
             * Method 1: traverse the data in the map, but the map itself has no iterator, so it needs to be converted into a set set first
             * Set<Key>:Store all Key values in the map into the set set -- keySet()
             */
            //4.1 take out the key value in the map Set and store it in the Set. The generic type of the Set is the type Integer of the key
            Set<Integer> keySet = map.keySet();
            //4.2 to traverse a set, you need to get the iterator of the set
            Iterator<Integer> it = keySet.iterator();
            //4.3 all elements in the loop iteration set
            while (it.hasNext()){ //Determine whether the next element can be iterated
                Integer key = it.next(); //Get the key of the map obtained in this cycle
                String value = map.get(key);
                System.out.println("{"+key+","+value+"}");
            }
    
            System.out.println("******************************");
    
            /**
             * Method 2: to traverse the map set, you need to convert the map set into a set set first,
             * Is to put a pair of key & value pairs in the map into the set as an entry < K, V >
             * A pair of K and V is an Entry
             */
            Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
            //Get iterator
            Iterator<Map.Entry<Integer, String>> it2 = entrySet.iterator();
            while (it2.hasNext()){
                Map.Entry<Integer, String> entry = it2.next();
                Integer key = entry.getKey();
                String value = entry.getValue();
                System.out.println("{"+key+","+value+"}");
            }
        }
    }
    
    

7.HashMap

  • Exercise: character frequency statistics in string
    package cn.tedu.list;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    //This class is used for character statistics cases in strings
    public class TestMap2 {
        public static void main(String[] args) {
            //Requirement: user inputs abcccc, output result: {a=1,b=1,c=4}
            //1. Prompt and receive the string entered by the user
            System.out.println("Please enter a string");
            String input = new Scanner(System.in).nextLine();
            //2. Create a Map structure to store data
            /**
             * It counts the number of occurrences of each letter. A single Character is a Character type, corresponding to a Character
             * Character The specified is a letter, which cannot be repeated, so select Character as the key
             * Integer It represents the number of times this letter appears. It can be repeated and cannot be used as value
             */
            Map<Character,Integer> map = new HashMap<>();
            //3. Traverse the data entered by the user
            /*               Mode 1                */
            for(int i = 0; i < input.length() ; i++){
                char key = input.charAt(i); //Gets the value at the specified subscript of the string
                System.out.println("Characters obtained:" + key);
                //4. Count the number of occurrences of each character
                Integer value = map.get(key); //View the data stored in the map and obtain the number of times value
                if (value == null){ //When null, it indicates that this letter appears for the first time (it has not been saved before)
                    map.put(key,1); //Save, (the number of letters currently obtained is 1)
                }else { //value is not null, indicating that it is not the first cycle, and this letter has appeared before
                    map.put(key,value+1);  //Save, (the number of times previously saved for the currently acquired letter + 1)
                }
            }
            System.out.println(map);
    
            /*               Mode II                */
            for(int i = 0; i < input.length() ; i++){
                char key = input.charAt(i);
                if(!map.containsKey(key)){
                    map.put(key,1);
                }else {
                    map.put(key,map.get(key)+1);
                }
            }
            System.out.println(map);
    
            /*               Mode III                */
            for(int i = 0; i < input.length() ; i++){
                char key = input.charAt(i); //Gets the value at the specified subscript of the string
                //4. Count the number of occurrences of each character
                map.merge(key, 1, Integer::sum);
            }
            System.out.println(map);
        }
    }
    
    
  • The third method is the new method in JDK8, map merge()
    • Source code excerpt
      default V merge(K key, V value,
              BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
          Objects.requireNonNull(remappingFunction);
          Objects.requireNonNull(value);
          V oldValue = get(key);
          V newValue = (oldValue == null) ? value :
                     remappingFunction.apply(oldValue, value);
          if(newValue == null) {
              remove(key);
          } else {
              put(key, newValue);
          }
          return newValue;
      }
      
      • merge() can be understood as: it assigns a new value to the key (if it does not exist) or updates the value corresponding to the given key value
      • The merge() method receives three parameters, a key value, a value value and a remappingFunction. If the given key does not exist, it becomes put(key, value).
      • However, if the key already has some values, the remappingFunction can select the merging method, and then assign the merged newValue to the original key
      • :: is a binocular operator in Java. It appears in Java 8. We can access class construction methods, object methods and static methods through the:: keyword. The static method sum, public static int sum (int a, int b) {return a + B;} in Integer is accessed here

8. Underlying implementation

  • Stored procedure:
    • The bottom layer of HashMap is an Entry [] array
    • When storing data, the key in the current Entry will be obtained for operation (algorithm hash(key)%n) to find out where the current Entry should be stored in the Entry [] array.
    • When the calculated position has no data, it is stored directly
    • After the key values of the two entries are calculated, the remainder is equal, that is, hash collision / hash collision will occur when the calculated position already has data
    • In case of conflict, the solution is to use the linked list structure. You can link the new entry to the old entry to form a linked list
    • When the length of the linked list is greater than 8, it will be turned into a red black tree, and when it is less than 6, it will be restored to a linked list
      • Source code excerpt
      • static final int TREEIFY_THRESHOLD = 8;
        static final int UNTREEIFY_THRESHOLD = 6;
        

  • There are two indicators that will affect the query efficiency of hashMap
    • Capacity: capacity will be expanded by about twice – initial capacity 16
    • Loading factor: expand the storage capacity to the extent of 0.75f
    • Source code excerpt
    • static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
      static final float DEFAULT_LOAD_FACTOR = 0.75f;
      
    • The capacity is the number of buckets in the hash table. The initial capacity is only the capacity of the hash table when it is created. Load factor is a measure of how full a hash table can be before its capacity automatically increases. Therefore, the loading factor is 0.75 by default, that is, the HashMap with a size of 16 will expand to 32 when it reaches the 13th element.
    • After the array is expanded, rehash the hash table (that is, rebuild the internal data structure)
    • Typically, the default load factor (. 75) seeks a compromise between time and space costs. High loading factor reduces the space overhead, but also increases the query cost. When setting the initial capacity, the number of entries required in the mapping and its loading factor should be considered in order to minimize the number of rehash operations.
  • Why does rehash happen?
    • When the initial capacity is 16, assume that the key of entry1, its hash code is 1, the remainder of 16 is 1, that is, it is placed in the position where the index of the array is 1, and there is another key of Entry2, its hash code is 17, and the remainder of 16 is 1, then it is connected to entry1 to form a linked list; However, if the array length becomes 32 After capacity expansion, the remainder of entry1 to 32 is 1 and placed at the position where the subscript is 1; If the remainder of Entry2 to 32 is 17, it should be placed at the position where the subscript is 17. Unlike before, it should be connected after entry1
    • Once the capacity is expanded and the array length is expanded from n to 2n, the hash value of each entry key may change the remainder of the array length (hash(key)%n), which means that the subscript of the entry in the array will also change, which is equivalent to reordering, that is, rehash.

9. Summary

  • Set
    • The data in the set is out of order, and the elements have no subscripts
    • set is not allowed to store duplicate data. null is allowed, but there is only one at most
    • If the custom object wants to be de duplicated, you need to override equals() and hashCode()
  • Map
    • The structure of map is < K, V >, which represents a pair of key value pairs (mapping relationship), and the corresponding values can be obtained according to the corresponding keys
    • The data stored in the map is unordered
    • The key in the map cannot be repeated, but the value can be repeated. If there are multiple different values corresponding to the same key, the latter value will overwrite the previous value
    • HashMap underlying structure: array + linked list or array + red black tree
      • Note: when to expand the capacity is related to the amount of data stored in the entry array, but not to whether to form a linked list, link several elements, or become a red black tree

Topics: Java set HashMap