【问题标题】:Enums Returning Arrays Stream枚举返回数组流
【发布时间】:2018-07-19 06:45:50
【问题描述】:

我需要根据一些预定义的值(将来可能会增长)来验证字段。因此,为此我创建了一个 Enum 并定义了一个返回允许值流的方法。

public enum EnumDemo {

    VERSION("1.0.0","2.0.3");

    private List<String> ver;

    EnumDemo(String... ver) {
        this.ver = Arrays.asList(ver);
    }

    public List<String> getVer() {
        return ver;
    }

    public static Stream<EnumDemo> stream() {
        return Arrays.stream(EnumDemo.values());
    }
}

现在我需要根据这个枚举中定义的值来验证一个字段。

我正在使用:

Optional<EnumDemo> ab = EnumDemo.stream()
.map(l -> {l.getVer().stream()
                     .filter(c -> c.equals("2.0.3"))
                     .findFirst();})
.findFirst();

System.out.println(ab.get().getVer());

但它给了我编译错误。任何帮助将不胜感激。

编辑:

编译错误:

The method map(Function<? super EnumDemo,? extends R>) in the type Stream<EnumDemo> is not applicable for the arguments ((<no type> l) -> {})

【问题讨论】:

  • 你能提供给我们错误信息吗?
  • 删除{;},或在{之后添加return
  • 如果你能显示实际错误而不是仅仅说“有一个错误”会有所帮助。
  • @Jai -- 没用 :(
  • 编译错误抱歉没有粘贴

标签: java enums java-8 java-stream


【解决方案1】:

你应该这样写:

Optional<EnumDemo> ab = EnumDemo.stream().filter(l -> l.getVer().contains("2.0.3"))
                                         .findFirst();

顺便说一句,它不起作用,因为您使用了 {} 作为 lambda 表达式,所以它在 {} 中期待 return 语句。您可以删除{}(连同;)或添加return

无论如何,原始代码看起来很混乱,不确定我是否猜对了意图,但这个实现应该更清晰。

编辑

根据您的评论,这是您需要的:

EnumDemo.stream().flatMap(l -> l.getVer().stream())
                 .filter("2.0.3"::equals)
                 .findAny()
                 .ifPresent(System.out::println);

更新

Holger 评论说有一种更短更有意义的方式,性能更好:

if(EnumDemo.stream()
           .anyMatch(l -> l.getVer().contains(userString))) {
    System.out.println(userString);
}

【讨论】:

  • 我已经试过了。但它会将完整列表返回给 Optional。我只需要与用户输入匹配的元素。 System.out.println(ab.get().getVer());打印 [1.0.0, 2.0.3]
  • @Abhishek 那是匹配的枚举,但是这个枚举 (EnumDemo.VERSION) 确实有超过 1 个版本值,这是正确的。
  • @Abhishek 显然人们现在对您误解,也许您可​​以添加一个演示/案例来澄清您的想法。顺便说一句,我认为在这里使用流不是一个好的选择。
  • 第二个 sn-p 不编译,删除:Optional&lt;EnumDemo&gt; ab = 或使用.peek 代替.ifPresent
  • 搜索匹配用户输入的字符串是没有意义的,因为用户输入本身已经是匹配用户输入的字符串。唯一相关的结果信息是该字符串是否有效,即boolean。所以你可以简单地使用if(EnumDemo.stream().anyMatch(l -&gt; l.getVer().contains(userString))) System.out.println(userString); 而不是flatMap 的东西。
【解决方案2】:

要理解它,您必须考虑 lambda。 Lambda 代表interfaces,但被 JVM 特殊处理,所以并不是每个 Lambda 都需要一个类来表示。 (无状态 lambda 可以只是方法)。

现在查看Stream 接口中的map() 方法时:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

您看到它需要一个Function 接口的实现。您现在有许多不同的方式来提供该映射器。在此示例中,让我们从 Object 映射到 String

1。使用内联 lambda:

.map(o -> o.toString())

2。使用多行 lambda:

.map(o -> { 
    return o.toString(); 
})

3。使用方法参考:

.map(Object::toString)

4。使用匿名类:

.map(new Function<Object, String>(){
     @Override
     public String apply(Object o){
         return o.toString();
     }
})

您当前的代码使用 2. 方法。但没有return 声明。在查看 4. 处的匿名类时,这一点更加明显。看起来很自然,当不在方法中使用 return 语句时不会返回任何值。

这就是你得到编译错误的原因。

您只需添加return 语句:

.map(l -> {
    return l.getVer().stream()
        .filter(c -> c.equals("2.0.3"))
        .findFirst();
});

或者去掉括号{}:

.map(l -> l.getVer().stream()
    .filter(c -> c.equals("2.0.3"))
    .findFirst());

甚至可以使用@Jai 在his answer 中提供的方法。比您目前拥有的效果更好。

【讨论】:

    【解决方案3】:

    您正在使用lambda 表达式并且没有返回任何值,因此它给出了编译错误。最好使用ifPresent()

    String val="2.0.3";
    EnumDemo.stream()
        .flatMap(l -> l.getVer().stream())
        .filter(c -> c.equals(val))
        .findAny()
        .ifPresent(x -> System.out.println(x));
    

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2015-02-14
      相关资源
      最近更新 更多