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
目录
相关文章
|
25天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
39 3
|
25天前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
78 3
|
25天前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
50 2
|
25天前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
79 2
|
6天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
14 2
|
6天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
10天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
10天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
10天前
|
Java 开发者
|
15天前
|
存储 Java API
Java交换map的key和value值
通过本文介绍的几种方法,可以在Java中实现Map键值对的交换。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。对于简单的键值对交换,可以使用简单遍历法或Java 8的Stream API;对于需要处理值不唯一的情况,可以使用集合存储或Guava的Multimap。希望本文对您理解和实现Java中的Map键值对交换有所帮助。
19 1