предисловие
За последние несколько дней я прочитал несколько зарубежных сообщений в блогах о Java Map, которые очень хорошо написаны, поэтому я разобрался с 8 вопросами, которые должны освоить Java Map, которые являются общими проблемами в ежедневной разработке, Надеюсь, это поможет. вы; если есть какое-то неправильное место, добро пожаловать, чтобы предложить, большое спасибо ~
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, поэтому это глубокая копия.
Ссылка и спасибо
- Top 9 questions about Java Maps
- Best way to create an empty map in Java
- Как клонировать HashMap — поверхностное и глубокое копирование
Личный публичный аккаунт
- Если вы хороший ребенок, который любит учиться, вы можете подписаться на мой официальный аккаунт, чтобы учиться и обсуждать вместе.
- Если вы считаете, что в этой статье есть какие-либо неточности, вы можете прокомментировать или подписаться на мой официальный аккаунт, пообщаться со мной в частном порядке, и все смогут учиться и прогрессировать вместе.