【问题标题】:How to give default value for a optional with generic type in JAVA如何在 JAVA 中为具有泛型类型的可选项提供默认值
【发布时间】:2019-07-17 15:38:00
【问题描述】:

非常感谢所有答案/cmets!

为我在原始问题中输入的错误代码示例道歉。我试图简化我的问题,但显然它最终变得相当混乱。

我稍微改了一下代码:

    Map<String, Boolean> map1 = new HashMap<>();
    map1.put("Yes", Boolean.FALSE);
    map1.put("No", Boolean.FALSE);

    Map<String, Map<String, List<String>>> map2 = new HashMap<>();
    List<String> list1 = Arrays.asList("Apple", "Peach");
    List<String> list2 = Arrays.asList("Pear", "Orange");
    Map<String, List<String>> innerMap = new HashMap<>();
    innerMap.put("fruit1", list1);
    innerMap.put("fruit2", list2);
    map2.put("Fruits", innerMap);
    map2.put("Vege", new HashMap<>());

    Optional<? extends Entry<String, ? extends Object>> optional = Stream
            .of(map1.entrySet().stream().filter(e -> e.getValue()).findFirst(),
                    map2.entrySet().stream().filter(entry -> entry.getValue().entrySet()
                            .stream()
                            .anyMatch(e -> e.getKey().equals("Fruit") && e.getValue().stream().anyMatch(
                                    i -> i.equals("Pear"))))
                            .findFirst())
            .filter(Optional::isPresent).map(Optional::get).findFirst();

    optional.orElse(new AbstractMap.SimpleEntry<>("NULL", null));

我得到了第一个错误:

无法推断 AbstractMap.SimpleEntry 的类型参数

所以我把最后一行改成:

   optional.orElse(new AbstractMap.SimpleEntry<String, Object>("NULL", null));

然后orElse上弹出一个新的错误:

Optional类型中的orElse(capture#4-of ? extends Map.Entry)方法不适用于参数(AbstractMap.SimpleEntry)

据我了解,两个 Map 具有相同的 Key 类型但不同的 Value 类型。每个地图的过滤器也不同。因此,返回的将是一个 Optional,其 Entry 类型为 Key,但具有泛型类型 Value。

我最初的问题是我不知道如何为此 Optional 提供默认值,因为 Entry 的 Value 类型是通用的(我现在仍然不知道答案)。

受@Ole 的启发,我重构了如下代码:

String result = Stream
            .of(map1.entrySet().stream().filter(e -> e.getValue()).map(Map.Entry::getKey).findFirst(), map2
                    .entrySet().stream().filter(entry -> entry.getValue().entrySet()
                            .stream()
                            .anyMatch(e -> e.getKey().contains("fruit") && e.getValue().stream().anyMatch(
                                    i -> i.equals("Pear"))))
                    .map(Map.Entry::getKey)
                    .findFirst())
            .filter(Optional::isPresent).map(Optional::get).findFirst().orElse("NULL");

System.out.println("result: " + result);

虽然我只将过滤后的条目的密钥收集到流中,但 JAVA 编译器似乎运行良好。我得到的执行结果为

结果:水果

但似乎我在这里仍然过于复杂......

【问题讨论】:

  • null 无法推断为? extends Object&amp;Serializable&amp;Comparable&lt;?&gt;。也许明确的演员会有所帮助

标签: java generics java-stream optional pecs


【解决方案1】:
    Map.Entry<String, ?> result = Stream.of(map1, map2)
            .flatMap(m -> m.entrySet().stream())
            .filter(e -> e.getKey().equals("Yes"))
            .findFirst()
            .orElse(new AbstractMap.SimpleEntry<>("NULL", null));
    System.out.println(result);

输出:

NULL=null

您使Optional 的处理从findFirst 变得过于复杂。不要使用isPresent 也不要使用getorElse 会为你做所有事情。

AbstractMap.SimpleEntry 也不需要类型参数。 Java 从参数("NULL", null) 推断出&lt;String, Object&gt;

我发现从地图流开始更容易,因此我们只需要指定一次我们要对地图做什么。

顺便说一句,您的每张地图都只有一个条目。您的第二个 put 操作具有相同的键,因此会覆盖第一个 put 调用中的条目。因此,在省略第一个调用时,您可以获得相同的结果。

【讨论】:

  • 说到复杂,通过Map流式传输,在按键上应用equals,绝对属于这一类,更不用说将O(1)操作变成O(n)操作. Object o = map1.getOrDefault("Yes", map2.get("Yes")); Map.Entry&lt;String, ?&gt; result = new AbstractMap.SimpleEntry&lt;&gt;(o == null? "NULL": "Yes", o); 会做同样的事情,不过,取决于 OP 实际想要对结果做什么,它可能会更简单。无论如何,考虑到map1.put("No", true); map1.put("No", false); 等,OP 方面似乎存在根本性的误解。
  • 感谢您的回答!!我用更多细节编辑了我原来的问题。
猜你喜欢
  • 2010-11-09
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-23
相关资源
最近更新 更多