8 вопросов, которые вы должны знать о Java Maps

Java

предисловие

За последние несколько дней я прочитал несколько зарубежных сообщений в блогах о Java Map, которые очень хорошо написаны, поэтому я разобрался с 8 вопросами, которые должны освоить Java Map, которые являются общими проблемами в ежедневной разработке, Надеюсь, это поможет. вы; если есть какое-то неправильное место, добро пожаловать, чтобы предложить, большое спасибо ~

Все демонстрации кода в этой главе загружены на github.

1. Как преобразовать карту в список

В повседневной разработке мы часто сталкиваемся с этим сценарием, преобразуя карту в список. Существует три метода преобразования карты в список:

  • Преобразование ключевого ключа карты в список
  • Преобразовать значение карты в список
  • Преобразовать ключ-значение карты в список

Псевдокод выглядит следующим образом:

// key list
List keyList = new ArrayList(map.keySet());
// value list
List valueList = new ArrayList(map.values());
// key-value list
List entryList = new ArrayList(map.entrySet());

Образец кода:

public class Test {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(2, "jay");
        map.put(1, "whx");
        map.put(3, "huaxiao");
        //把一个map的键转化为list
        List<Integer> keyList = new ArrayList<>(map.keySet());
        System.out.println(keyList);
        //把map的值转化为list
        List<String> valueList = new ArrayList<>(map.values());
        System.out.println(valueList);
        把map的键值转化为list
        List entryList = new ArrayList(map.entrySet());
        System.out.println(entryList);

    }
}

результат операции:

[1, 2, 3]
[whx, jay, huaxiao]
[1=whx, 2=jay, 3=huaxiao]

2. Как перемещаться по карте

Нам часто нужно пройти по карте, что может быть достигнуто следующими двумя способами:

Обход через entrySet+for

for(Entry entry: map.entrySet()) {
  // get key
  K key = entry.getKey();
  // get value
  V value = entry.getValue();
}

Пример кода:

public class EntryMapTest {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(2, "jay");
        map.put(1, "whx");
        map.put(3, "huaxiao");

        for(Map.Entry entry: map.entrySet()) {
            // get key
            Integer key = (Integer) entry.getKey();
            // get value
            String value = (String) entry.getValue();

            System.out.println("key:"+key+",value:"+value);
        }
    }
}

Обход через итератор+пока

Iterator itr = map.entrySet().iterator();
while(itr.hasNext()) {
  Entry entry = itr.next();
  // get key
  K key = entry.getKey();
  // get value
  V value = entry.getValue();
}

Пример кода:

public class IteratorMapTest {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(2, "jay");
        map.put(1, "whx");
        map.put(3, "huaxiao");

        Iterator itr = map.entrySet().iterator();
        while(itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            // get key
            Integer key = (Integer) entry.getKey();
            // get value
            String value = (String) entry.getValue();

            System.out.println("key:"+key+",value:"+value);
        }
    }
}

результат операции:

key:1,value:whx
key:2,value:jay
key:3,value:huaxiao

3. Как сортировать по ключам Карты

Сортировка ключей Map очень распространена в повседневной разработке, и есть два основных способа добиться этого.

Поместите Map.Entry в список, а затем используйте Comparator для сортировки списка.

List list = new ArrayList(map.entrySet());
Collections.sort(list, (Entry e1, Entry e2)-> {
    return e1.getKey().compareTo(e2.getKey());
});

Пример кода:

public class SortKeysMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("2010", "jay");
        map.put("1999", "whx");
        map.put("3010", "huaxiao");

        List<Map.Entry<String,String>> list = new ArrayList<>(map.entrySet());
        Collections.sort(list, (Map.Entry e1, Map.Entry e2)-> {
                return e1.getKey().toString().compareTo(e2.getKey().toString());
        });

        for (Map.Entry entry : list) {
            System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue());
        }

    }
}

Реализовано с помощью SortedMap+TreeMap+Comparator

SortedMap sortedMap = new TreeMap(new Comparator() {
  @Override
  public int compare(K k1, K k2) {
    return k1.compareTo(k2);
  }
});
sortedMap.putAll(map);

Пример кода:

public class SortKeys2MapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("2010", "jay");
        map.put("1999", "whx");
        map.put("3010", "huaxiao");

        SortedMap sortedMap = new TreeMap(new Comparator<String>() {
            @Override
            public int compare(String k1, String k2) {
                return k1.compareTo(k2);
            }
        });
        sortedMap.putAll(map);

        Iterator itr = sortedMap.entrySet().iterator();
        while(itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            // get key
            String key = (String) entry.getKey();
            // get value
            String value = (String) entry.getValue();

            System.out.println("key:"+key+",value:"+value);
        }
    }
}

результат операции:

key:1999,value:whx
key:2010,value:jay
key:3010,value:huaxiao

4. Как отсортировать значения Map

List list = new ArrayList(map.entrySet());
Collections.sort(list, (Entry e1, Entry e2) ->{
    return e1.getValue().compareTo(e2.getValue());
  });

Пример кода:

public class SortValuesMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("2010", "jay");
        map.put("1999", "whx");
        map.put("3010", "huaxiao");

        List <Map.Entry<String,String>>list = new ArrayList<>(map.entrySet());
        Collections.sort(list, (Map.Entry e1, Map.Entry e2)-> {
                return e1.getValue().toString().compareTo(e2.getValue().toString());
            }
        );

        for (Map.Entry entry : list) {
            System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue());
        }
    }
}

результат операции:

key:3010,value:huaxiao
key:2010,value:jay
key:1999,value:whx

5. Как инициализировать статическую/неизменяемую карту

Чтобы инициализировать статическую неизменяемую карту, одного кода static final+static недостаточно, а именно:

public class Test1 {
    private static final Map <Integer,String>map;
    static {
        map = new HashMap<Integer, String>();
        map.put(1, "one");
        map.put(2, "two");
    }
    public static void main(String[] args) {
        map.put(3, "three");
        Iterator itr = map.entrySet().iterator();
        while(itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            // get key
            Integer key = (Integer) entry.getKey();
            // get value
            String value = (String) entry.getValue();

            System.out.println("key:"+key+",value:"+value);
        }
    }
}

Здесь карта продолжает добавлять элементы (3, «три»), и все в порядке. Результаты следующие:

key:1,value:one
key:2,value:two
key:3,value:three

Чтобы действительно реализовать статическую неизменяемую карту, требуется Collections.unmodifiedMap Код выглядит следующим образом:

public class Test2 {
    private static final Map<Integer, String> map;
    static {
        Map<Integer,String> aMap = new HashMap<>();
        aMap.put(1, "one");
        aMap.put(2, "two");
        map = Collections.unmodifiableMap(aMap);
    }

    public static void main(String[] args) {
        map.put(3, "3");
        Iterator itr = map.entrySet().iterator();
        while(itr.hasNext()) {
            Map.Entry entry = (Map.Entry) itr.next();
            // get key
            Integer key = (Integer) entry.getKey();
            // get value
            String value = (String) entry.getValue();

            System.out.println("key:"+key+",value:"+value);
        }
    }

}

Результаты приведены ниже:

Можно обнаружить, что если вы продолжите добавлять элементы на карту, будет сообщено об ошибке, реализуя действительно неизменяемую карту.

6. Разница между HashMap, TreeMap и Hashtable, ConcurrentHashMap

HashMap TreeMap Hashtable ConcurrentHashMap
упорядоченность нет да нет нет
null k-v Да Да нет да нет нет нет нет
Линейная безопасность нет нет да да
временная сложность О(1) О (журнал п) O(1) О (журнал п)
базовая структура массив + связанный список красно-черное дерево массив + связанный список красно-черное дерево

7. Как создать пустую карту

Если карта неизменяемая, ее можно создать так:

Map map=Collections.emptyMap();
or
Map<String,String> map=Collections.<String, String>emptyMap();
//map1.put("1", "1"); 运行出错

Если вы хотите, чтобы ваша пустая карта могла добавлять элементы, вы можете создать ее следующим образом.

Map map = new HashMap();

8. О копировании карты

Есть копия hashmap, которая больше используется в повседневной разработке. Есть=,clone,putAll, но все они являются мелкими копиями, будьте внимательны при их использовании, вы можете взглянуть на следующие примеры:

Пример 1, использование = для копирования карты:

public class CopyMapAssignTest {
    public static void main(String[] args) {

        Map<Integer, User> userMap = new HashMap<>();

        userMap.put(1, new User("jay", 26));
        userMap.put(2, new User("fany", 25));

        //Shallow clone
        Map<Integer, User> clonedMap = userMap;

        //Same as userMap
        System.out.println(clonedMap);

        System.out.println("\nChanges reflect in both maps \n");

        //Change a value is clonedMap
        clonedMap.get(1).setName("test");

        //Verify content of both maps
        System.out.println(userMap);
        System.out.println(clonedMap);
    }
}

результат операции:

{1=User{name='jay', age=26}, 2=User{name='fany', age=25}}

Changes reflect in both maps 

{1=User{name='test', age=26}, 2=User{name='fany', age=25}}
{1=User{name='test', age=26}, 2=User{name='fany', age=25}}

Из бегущих результатов видно, что для модификации cloneMap обе карты изменились, так что = — мелкая копия.

Пример 2, клонирование копии с использованием хэш-карты:

public class CopyCloneMapTest {
    public static void main(String[] args) {
        HashMap<Integer, User> userMap = new HashMap<>();

        userMap.put(1, new User("jay", 26));
        userMap.put(2, new User("fany", 25));

        //Shallow clone
        HashMap<Integer, User> clonedMap = (HashMap<Integer, User>) userMap.clone();

        //Same as userMap
        System.out.println(clonedMap);

        System.out.println("\nChanges reflect in both maps \n");

        //Change a value is clonedMap
        clonedMap.get(1).setName("test");

        //Verify content of both maps
        System.out.println(userMap);
        System.out.println(clonedMap);
    }
}

результат операции:

{1=User{name='jay', age=26}, 2=User{name='fany', age=25}}

Changes reflect in both maps 

{1=User{name='test', age=26}, 2=User{name='fany', age=25}}
{1=User{name='test', age=26}, 2=User{name='fany', age=25}}

Из текущих результатов видно, что при изменении cloneMap обе карты изменились, поэтому клон хэш-карты также является поверхностной копией.

Пример 3, через операцию putAll

public class CopyPutAllMapTest {
    public static void main(String[] args) {
        HashMap<Integer, User> userMap = new HashMap<>();

        userMap.put(1, new User("jay", 26));
        userMap.put(2, new User("fany", 25));

        //Shallow clone
        HashMap<Integer, User> clonedMap = new HashMap<>();
        clonedMap.putAll(userMap);

        //Same as userMap
        System.out.println(clonedMap);

        System.out.println("\nChanges reflect in both maps \n");

        //Change a value is clonedMap
        clonedMap.get(1).setName("test");

        //Verify content of both maps
        System.out.println(userMap);
        System.out.println(clonedMap);
    }
}

результат операции:

{1=User{name='jay', age=26}, 2=User{name='fany', age=25}}

Changes reflect in both maps 

{1=User{name='test', age=26}, 2=User{name='fany', age=25}}
{1=User{name='test', age=26}, 2=User{name='fany', age=25}}

Из текущих результатов видно, что при изменении cloneMap обе карты изменились, поэтому putAll по-прежнему является поверхностной копией.

Итак, как реализовать глубокую копию?

Можно использовать сериализацию.Ниже приведен пример сериализации HashMap в Google Gson для реализации глубокого копирования:

public class CopyDeepMapTest {

    public static void main(String[] args) {
        HashMap<Integer, User> userMap = new HashMap<>();

        userMap.put(1, new User("jay", 26));
        userMap.put(2, new User("fany", 25));

        //Shallow clone
        Gson gson = new Gson();
        String jsonString = gson.toJson(userMap);

        Type type = new TypeToken<HashMap<Integer, User>>(){}.getType();
        HashMap<Integer, User> clonedMap = gson.fromJson(jsonString, type);

        //Same as userMap
        System.out.println(clonedMap);

        System.out.println("\nChanges DO NOT reflect in other map \n");

        //Change a value is clonedMap
        clonedMap.get(1).setName("test");

        //Verify content of both maps
        System.out.println(userMap);
        System.out.println(clonedMap);
    }
}

результат операции:

{1=User{name='jay', age=26}, 2=User{name='fany', age=25}}

Changes DO NOT reflect in other map 

{1=User{name='jay', age=26}, 2=User{name='fany', age=25}}
{1=User{name='test', age=26}, 2=User{name='fany', age=25}}

Из текущих результатов видно, что userMap не был изменен для модификации cloneMap, поэтому это глубокая копия.

Ссылка и спасибо

Личный публичный аккаунт

  • Если вы хороший ребенок, который любит учиться, вы можете подписаться на мой официальный аккаунт, чтобы учиться и обсуждать вместе.
  • Если вы считаете, что в этой статье есть какие-либо неточности, вы можете прокомментировать или подписаться на мой официальный аккаунт, пообщаться со мной в частном порядке, и все смогут учиться и прогрессировать вместе.