Java Map 通过 key 或者 value 过滤

本文介绍了如何使用Java 8的Lambda表达式以及Guava库来过滤Map中的元素,分别展示了根据key和value进行过滤的示例代码。文章提供了必要的依赖引用,并鼓励读者关注作者。

今天写根过滤的时候一下子有点愣眼,先是想到用 Java 原生的 map 循环查出来,但是觉得太 low, 后面思考了一下可以用 Java8 的 Lambda,写完了,又发现 Google Guava 有现成的方法,这里一一列出来,供参考使用。

首先提示,如果照搬我的代码的话别忘了引这些依赖

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>

    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-library</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>25.1-jre</version>
    </dependency>

</dependencies>
filter by key
public class FilterMapByKeyTest {
private Map<Integer, String> WEEK = new HashMap<>();

@Before
public void setUp () {
    WEEK.put(1, "Monday");
    WEEK.put(2, "Tuesday");
    WEEK.put(3, "Wednesday");
    WEEK.put(4, "Thursday");
    WEEK.put(5, "Friday");
    WEEK.put(6, "Saturday");
    WEEK.put(7, "Sunday");
}

/**
 * Java 8之前的版本
 */
@Test
public void filterMapByKey () {
    Map<Integer, String> map = new HashMap<>();
    for (Map.Entry<Integer, String> entry : WEEK.entrySet()) {
        if (entry.getKey() <= 3) {
            map.put(entry.getKey(), entry.getValue());
        }
    }
    assertThat(map.keySet(), contains(1, 2, 3));
}

/**
 * Java 8 Lambda
 */
@Test
public void filterMapByKeyJava8Lambda () {
    Map<Integer, String> map = WEEK.entrySet().stream().filter(r -> r.getKey() <= 3)
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    assertThat(map.keySet(), contains(1, 2, 3));
}

/**
 * Google Guava
 */
@Test
public void filterMapByKeyGuava () {
    Map<Integer, String> map = Maps.filterKeys(WEEK, r -> r <= 3);
    assertThat(map.keySet(), contains(1, 2, 3));
}

}
filter by value
public class FilterMapByValueTest {
private Map<Integer, String> WEEK = new HashMap<>();

@Before
public void setUp () {
    WEEK.put(1, "Monday");
    WEEK.put(2, "Tuesday");
    WEEK.put(3, "Wednesday");
    WEEK.put(4, "Thursday");
    WEEK.put(5, "Friday");
    WEEK.put(6, "Saturday");
    WEEK.put(7, "Sunday");
}

/**
 * Java 8之前的版本
 */
@Test
public void filterMapByValue () {
    Map<Integer, String> map = new HashMap<>();
    for (Map.Entry<Integer, String> entry : WEEK.entrySet()) {
        if (entry.getValue().startsWith("S")) {
            map.put(entry.getKey(), entry.getValue());
        }
    }
    assertThat(map.values(), contains("Saturday","Sunday"));
}

/**
 * Java 8 Lambda
 */
@Test
public void filterMapByValueJava8Lambda () {
    Map<Integer, String> map = WEEK.entrySet().stream().filter(r -> r.getValue().startsWith("S"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    assertThat(map.values(), contains("Saturday","Sunday"));
}

/**
 * Google Guava
 */
@Test
public void filterMapByValueGuava () {
    Map<Integer, String> map = Maps.filterValues(WEEK, r -> r.startsWith("S"));
    assertThat(map.values(), contains("Saturday","Sunday"));
}

}
如果觉得内容还不错,可以关注一下我哦

<think>好的,我现在需要解决用户的问题:如何使用Java Stream流来修改Map中特定Key对应的Value值。用户希望看到示例代码,所以我得先理清思路,确保方法正确。 首先,用户提到了使用Stream流,所以应该利用Java 8的Stream API来处理Map。根据引用[1],用户之前有对Map根据Key进行排序的例子,这可能涉及到Stream操作Map的entry。但这里的目标是修改特定KeyValue,而不是排序。 接下来,我需要考虑如何遍历Map的Entry,找到目标Key,并修改其Value。由于Stream本身是处理数据流的,可能需要使用map操作来转换每个Entry。不过,需要注意的是,直接修改原有的Entry可能不符合函数式编程的原则,应该生成新的Entry。 然后,考虑如何处理Key的匹配。比如,当遍历每个Entry时,如果Entry的Key等于目标Key,就修改Value,否则保持不变。这可以通过在map操作中使用条件判断来实现。 另外,用户提供的引用[3]中,处理重复Key时使用了Collectors.toMap,并提供了merge函数。这可能对收集结果时的冲突处理有帮助,但在这里主要是修改特定KeyValue,可能不需要处理重复Key的问题。不过,需要注意的是,如果使用Collectors.toMap,默认情况下如果有重复Key会抛出异常,但在这个场景中,因为原始MapKey应该是唯一的,所以可能不需要merge函数,但为了安全起见,可以保留一个合并函数,例如选择保留旧值或新值。 另外,引用[5]提到过滤MapKeyValue为空的情况,但用户的问题不涉及过滤,而是修改特定Key的值。不过,可能需要确保在修改过程中不会引入空值,或者处理可能的异常情况。 现在,整理步骤: 1. 将Map转换为Entry的Stream。 2. 使用map操作处理每个Entry:如果Key是目标,则创建新的Entry,否则保留原Entry。 3. 收集结果到一个新的Map中。 需要注意的是,JavaMap.Entry是不可变的,所以需要创建新的AbstractMap.SimpleEntry实例来替换原有的Entry。 例如,假设原MapMap<String, Integer>,要修改Key为"a"的Value为100: 代码可能如下: Map<String, Integer> originalMap = ...; Map<String, Integer> modifiedMap = originalMap.entrySet().stream() .map(entry -> { if ("a".equals(entry.getKey())) { return new AbstractMap.SimpleEntry<>(entry.getKey(), 100); } else { return entry; } }) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 但是这里可能会有问题,因为当直接返回原来的Entry时,Collectors.toMap可能会遇到重复的Key,但原Map中的Key应该是唯一的,所以不会有冲突。不过,为了安全起见,可以添加merge函数,比如 (oldVal, newVal) -> newVal,确保如果有重复,保留后者。 另外,引用[2]提到key重复会抛出异常,所以在collect的时候需要处理。但在这个场景中,由于每个Entry的Key在原Map中是唯一的,并且修改后的Entry的Key没有变化,所以不会有重复,因此不需要merge函数。但为了代码的健壮性,最好还是加上。 因此,collect部分可以写成: .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> newVal )); 这样即使有重复Key,也会保留最新的值,虽然在这个情况下应该不会出现。 测试一下示例代码是否正确。例如,原Map是{"a":1, "b":2},修改"a"为100,结果应该是{"a":100, "b":2}。 另外,需要考虑原Map是否是可变的。使用Stream的方式会生成新的Map,不会影响原Map,这是符合函数式编程的不变性原则的。 现在,根据上述思路,编写示例代码,并解释每一步的作用。同时,引用相关的引用文献,比如引用[1]中的Stream操作,引用[3]中的Collectors.toMap用法,以及处理重复Key的merge函数。</think>### 解决方案 使用Java Stream修改Map中特定KeyValue值,可以通过以下步骤实现: 1. 将Map转换为`Entry`流 2. 使用`map`操作替换目标KeyValue 3. 通过`Collectors.toMap`重新收集为Map对象 需注意处理Key重复问题(即使原Map无重复)以增强健壮性[^2]。 #### 示例代码 ```java import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class ModifyMapValue { public static void main(String[] args) { Map<String, Integer> originalMap = new HashMap<>(); originalMap.put("a", 1); originalMap.put("b", 2); originalMap.put("c", 3); // 使用Stream修改Key为"b"的Value值为200 Map<String, Integer> modifiedMap = originalMap.entrySet().stream() .map(entry -> { if ("b".equals(entry.getKey())) { // 创建新Entry替换目标值 return new AbstractMap.SimpleEntry<>(entry.getKey(), 200); } else { return entry; // 非目标Key保持原值 } }) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> newVal // 处理Key重复的合并策略 )); System.out.println(modifiedMap); // 输出:{a=1, b=200, c=3} } } ``` #### 关键说明 1. **`AbstractMap.SimpleEntry`**:创建新的键值对对象实现Value替换 2. **合并函数`(oldVal, newVal) -> newVal`**:显式声明冲突处理策略,避免潜在的`IllegalStateException`[^2] 3. **保持原Map不变**:Stream操作始终生成新Map,符合函数式编程特性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值