Java基础之集合Map

简介: 【7月更文挑战第8天】Java中的Map集合以键值对方式存储数据,如`Map<"name", "张三">`。Map接口定义了存取、判断、移除等操作,包括`put`、`get`、`containsKey`等方法。HashMap是最常用的实现,基于哈希表,允许null键值,但不保证顺序。其他实现包括同步的Hashtable、处理属性文件的Properties、保持插入顺序的LinkedHashMap、基于红黑树的TreeMap、弱引用的WeakHashMap、并发安全的ConcurrentHashMap和针对枚举优化的EnumMap。

Java基础之集合Map
在java.util包中的集合类包含了除List之外还有另一套常用集合类:Map。
Map提供了一个更通用的元素存储方法,那就是“键值对”存储。
元素对(称作“键”和“值”),其中每个键映射到一个值。
如果说数组或者集合中的某一个值是通过下标来获取,那么Map中的值就是通过对应的键来获取。
比如我们有一个要暂存一个名字是张三的数据,Map就可以供我们设置键是name,值是张三:Map<"name", "张三">
Map接口
首先也是看根接口:Map接口,这里的K就是key键,V就是value值。
Map接口中定义了通用的存(put)取(get)方法,还有一些判空isEmpty、移除键值对remove、清空clear等等。

  抽象类AbstractMap<K,V>实现了Map<K,V>接口,我们也可以通过继承AbstractMap<K,V>抽象类来实现自己的Map。

  Java内部提供了一些实现:
  HashMap:基于哈希表的Map接口实现。允许使用null键和null值。不保证映射的顺序;特别是它不保证顺序会随着时间的推移保持不变。最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。
  代码示例:
  // 创建一个HashMap
  Map<String, Integer> map = new HashMap<>();
  // 添加键值对
  map.put("One", 1);
  map.put("Two", 2);
  map.put("Three", 3);
  // 访问键值对
  int value = map.get("Two"); // 返回2
  System.out.println("Value of 'Two': " + value);
  // 检查是否包含键或值
  boolean containsKey = map.containsKey("One"); // 返回true
  boolean containsValue = map.containsValue(3); // 返回true
  System.out.println("Contains key 'One': " + containsKey);
  System.out.println("Contains value 3: " + containsValue);
  // 获取所有键的集合
  Set<String> keys = map.keySet();
  System.out.println("Keys: " + keys);
  // 获取所有值的集合
  Collection<Integer> values = map.values();
  System.out.println("Values: " + values);
  // 获取所有键值对的集合
  Set<Map.Entry<String, Integer>> entries = map.entrySet();
  for (Map.Entry<String, Integer> entry : entries) {
      System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
  }
  // 删除一个键值对
  int removedValue = map.remove("One"); // 返回1
  System.out.println("Removed value: " + removedValue);
  // 替换一个键值对
  map.replace("Two", 22);
  System.out.println("Map after replacement: " + map);
  // 如果键不存在,则添加键值对
  map.putIfAbsent("Four", 4);
  System.out.println("Map after putIfAbsent: " + map);
  // 获取键对应的值,如果键不存在,则返回默认值
  int defaultValue = map.getOrDefault("Five", 5);
  System.out.println("Default value for 'Five': " + defaultValue);
  // 检查Map是否为空
  boolean isEmpty = map.isEmpty();
  System.out.println("Is map empty? " + isEmpty);
  // 获取Map的大小
  int size = map.size();
  System.out.println("Size of map: " + size);
  // 清空Map
  map.clear();
  System.out.println("Map after clear: " + map);
  Hashtable:类似于HashMap,但是它是同步的。不允许使用null键或null值。现在已经被ConcurrentHashMap替代,因为后者提供了更好的并发性能。
  // Hashtable
  Map<String, Integer> hashtable = new Hashtable<>();
  hashtable.put("Two", 2);
  System.out.println("Hashtable: " + hashtable);

  Properties:用于处理属性文件。键和值都是字符串。项目中的配置文件一般就是这个。
  代码示例:
  // Properties
  Properties properties = new Properties();
  properties.setProperty("Three", "3");
  System.out.println("Properties: " + properties);

  LinkedHashMap:继承自HashMap,维护了插入的顺序。
  代码示例:
  // LinkedHashMap
  Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
  linkedHashMap.put("Four", 4);
  System.out.println("LinkedHashMap: " + linkedHashMap);

  IdentityHashMap:使用==而不是equals来比较键。主要用于需要保持键的身份信息的情况。
  代码示例:
  // IdentityHashMap
  Map<String, Integer> identityHashMap = new IdentityHashMap<>();
  identityHashMap.put(new String("Five"), 5);
  System.out.println("IdentityHashMap: " + identityHashMap);

  TreeMap:基于红黑树的实现,实现了SortedMap接口。可以确保键的顺序。能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
  代码示例:
  // TreeMap
  Map<String, Integer> treeMap = new TreeMap<>();
  treeMap.put("Six", 6);
  System.out.println("TreeMap: " + treeMap);

  WeakHashMap:允许键对象被垃圾回收器回收。主要用于缓存实现。
  代码示例:
  // WeakHashMap
  Map<String, Integer> weakHashMap = new WeakHashMap<>();
  weakHashMap.put("Seven", 7);
  System.out.println("WeakHashMap: " + weakHashMap);

  ConcurrentHashMap:支持高并发性的哈希表实现。允许多个线程并发访问,并且是线程安全的。
  代码示例:
  // ConcurrentHashMap
  Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
  concurrentHashMap.put("Eight", 8);
  System.out.println("ConcurrentHashMap: " + concurrentHashMap);

  EnumMap:键必须是枚举类型。它的性能比传统的HashMap要高,因为它是针对枚举类型优化的。
  代码示例:
  // EnumMap
  Map<Day, String> enumMap = new EnumMap<>(Day.class);
  enumMap.put(Day.MONDAY, "Monday");
  System.out.println("EnumMap: " + enumMap);
      }

      enum Day {
          MONDAY, TUESDAY, WEDNESDAY
      }
  }

  SortedMap:接口,不是实现,但是可以用于创建排序的映射。
  // SortedMap 示例
  SortedMap<String, Integer> sortedMap = new TreeMap<>();
  sortedMap.put("Three", 3);
  sortedMap.put("One", 1);
  sortedMap.put("Two", 2);
  // 按顺序遍历SortedMap
  System.out.println("SortedMap:");
  for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
      System.out.println(entry.getKey() + ": " + entry.getValue());
  }

  NavigableMap:扩展了SortedMap,提供了更多的导航方法。如headMap、tailMap和subMap,这些方法允许我们获取映射的子集。
  // NavigableMap 示例
  NavigableMap<String, Integer> navigableMap = new TreeMap<>(sortedMap);
  // 使用headMap返回小于指定键的子映射
  NavigableMap<String, Integer> headMap = navigableMap.headMap("Two", true);
  System.out.println("HeadMap (<= 'Two'): " + headMap);
  // 使用tailMap返回大于等于指定键的子映射
  NavigableMap<String, Integer> tailMap = navigableMap.tailMap("Two");
  System.out.println("TailMap (>= 'Two'): " + tailMap);
  // 使用subMap返回指定范围内的子映射
  NavigableMap<String, Integer> subMap = navigableMap.subMap("One", false, "Three", true);
  System.out.println("SubMap ('One', 'Three'): " + subMap);
  // 获取第一个键和对应的值
  Map.Entry<String, Integer> firstEntry = navigableMap.firstEntry();
  System.out.println("First Entry: " + firstEntry.getKey() + ": " + firstEntry.getValue());
  // 获取最后一个键和对应的值
  Map.Entry<String, Integer> lastEntry = navigableMap.lastEntry();
  System.out.println("Last Entry: " + lastEntry.getKey() + ": " + lastEntry.getValue());


  自定义Map实现: AbstractMap提供了Map接口的基本实现,以减少实现Map接口的工作量。可以用来创建自定义Map实现
  示例:
  class CustomMap extends AbstractMap<String, Integer> {
      private Map<String, Integer> innerMap = new HashMap<>();

      @Override
      public Set<Entry<String, Integer>> entrySet() {
          return innerMap.entrySet();
      }

      public void putCustom(String key, Integer value) {
          innerMap.put(key, value);
      }
  }
  CustomMap customMap = new CustomMap();
  customMap.putCustom("One", 1);
  customMap.putCustom("Two", 2);
  System.out.println("CustomMap: " + customMap);

  最常用的就是HashMap和SetMap,其他的了解即可。

  几种遍历方法:
  for遍历:
  上面示例已经有过,可以使用keySet()方法来获取所有key列表,然后通过get(key)来获取对应的值,以实现遍历当前Map:
  // 使用keySet()遍历
  for (String key : map.keySet()) {
      System.out.println(key + " :" + map.get(key));
  }
  // 使用entrySet()遍历
  for (Map.Entry<String, String> entry : map.entrySet()) {
      System.out.println(entry.getKey() + " :" + entry.getValue());
  }
  迭代器遍历:
  // 使用keySet()遍历
  Iterator<String> iterator = map.keySet().iterator();
  while (iterator.hasNext()) {
      String key = iterator.next();
      System.out.println(key + " :" + map.get(key));
  }
  // 使用entrySet()遍历
  Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
  while (iterator.hasNext()) {
      Map.Entry<String, String> entry = iterator.next();
      System.out.println(entry.getKey() + " :" + entry.getValue());
  }

  遍历性能速度:
  entrySet遍历的速度要比keySet快
  迭代器的遍历速度要比增强for循环快, 增强for循环使用方便,但不适合处理超大量级的数据。
  END
目录
相关文章
|
26天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
6天前
|
存储 算法 安全
深入理解Java中的集合框架
【9月更文挑战第34天】本文将带你走进Java的集合框架,探索其背后的设计哲学和实现细节。我们将从集合的基本概念出发,逐步深入到具体的接口和类的实现,最后通过一个实际的例子来展示如何在Java程序中高效地使用集合。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和深度理解。
12 1
|
29天前
|
Java C# Swift
Java Stream中peek和map不为人知的秘密
本文通过一个Java Stream中的示例,探讨了`peek`方法在流式处理中的应用及其潜在问题。首先介绍了`peek`的基本定义与使用,并通过代码展示了其如何在流中对每个元素进行操作而不返回结果。接着讨论了`peek`作为中间操作的懒执行特性,强调了如果没有终端操作则不会执行的问题。文章指出,在某些情况下使用`peek`可能比`map`更简洁,但也需注意其懒执行带来的影响。
Java Stream中peek和map不为人知的秘密
|
14天前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19
|
13天前
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
16天前
|
存储 安全 Java
Java 常用集合分类
Java 常用集合分类
13 2
|
1天前
|
存储 分布式计算 Java
Stream很好,Map很酷,但答应我别用toMap():Java开发中的高效集合操作
在Java的世界里,Stream API和Map集合无疑是两大强大的工具,它们极大地简化了数据处理和集合操作的复杂度。然而,在享受这些便利的同时,我们也应当警惕一些潜在的陷阱,尤其是当Stream与Map结合使用时。本文将深入探讨Stream与Map的优雅用法,并特别指出在使用toMap()方法时需要注意的问题,旨在帮助大家在工作中更高效、更安全地使用这些技术。
8 0
|
2月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
32 5
|
2月前
|
存储 Java 程序员
Java中的集合框架:从入门到精通
【8月更文挑战第30天】在Java的世界里,集合框架是一块基石,它不仅承载着数据的存储和操作,还体现了面向对象编程的精髓。本篇文章将带你遨游Java集合框架的海洋,从基础概念到高级应用,一步步揭示它的奥秘。你将学会如何选择合适的集合类型,掌握集合的遍历技巧,以及理解集合框架背后的设计哲学。让我们一起探索这个强大工具,解锁数据结构的新视角。
|
2月前
|
存储 算法 Java
Java中的集合框架深度解析云上守护:云计算与网络安全的协同进化
【8月更文挑战第29天】在Java的世界中,集合框架是数据结构的代言人。它不仅让数据存储变得优雅而高效,还为程序员提供了一套丰富的工具箱。本文将带你深入理解集合框架的设计哲学,探索其背后的原理,并分享一些实用的使用技巧。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往高效编程的大门。