【问题标题】:Map key value to an object in Java 8 stream将键值映射到 Java 8 流中的对象
【发布时间】:2023-03-15 10:00:01
【问题描述】:

假设我有这个代码:

Map<String, String> map;
// later on
map.entrySet().stream().map(MyObject::new).collect(Collectors.toList());

我有一个MyObjectConstructor,它接受两个String 类型的参数。 我希望能够做到这一点,但我做不到。 我知道我可以做到e -&gt; new MyObject(e.getKey(), e.getValue()),但更喜欢MyObject::new

类似的代码适用于Set&lt;String&gt;List&lt;String&gt;,具有MyObject 类的一个参数构造函数。

【问题讨论】:

  • map 函数不知道 2 个必要的 Strings 位于 Map.Entry 实例内部的某个位置。您必须手动提取键和值,因此您需要使用e.getKey()e.getValue()
  • 为什么更喜欢方法参考?当它符合要求时它很优雅,但在这里它不符合要求。
  • this
  • 您可以使用来自this answerPairStreamPairStream.from(map).map(MyObject::new).collect(Collectors.toList());

标签: java constructor java-8 mapping java-stream


【解决方案1】:

使用 lambda:

map.entrySet()
   .stream()
   .map(e -> new MyObject(e.getKey(), e.getValue()))
   .collect(Collectors.toList());

否则,使用方法引用的唯一方法是创建这样的函数:

private static MyObject apply(Map.Entry<String, String> e) {
      return new MyObject(e.getKey(), e.getValue());
}

然后执行以下操作:

map.entrySet()
   .stream()
   .map(Main::apply)
   .collect(Collectors.toList());

其中Main 是包含apply 方法的类。

【讨论】:

    【解决方案2】:
    map.entrySet().stream().map(MyObject::new).collect(Collectors.toList()));
    

    我有一个MyObject 构造函数,它接受两个String 类型的参数。我希望能够做到这一点,但我做不到。

    map.entrySet().stream().map(...) 中,Java 期待Function, 将一个值映射到另一个值。 一值。 从流中,函数接收Map.Entry&lt;String, String&gt; 类型的值, 但是您的构造函数需要两个 String 参数。 Java 不会自动将 Map.Entry&lt;String, String&gt; 扩展为一对 Strings 以传递给您的构造函数。 你必须手动解包。

    【讨论】:

      【解决方案3】:

      添加 Map.Entry 构造函数

      class MyObject {
              private final String k;
              private final String v;
      
              MyObject(String s1, String s2) {
                  k = s1;
                  v = s2;
              }
      
              MyObject(Map.Entry<String, String> e) {
                  this(e.getKey(), e.getValue());
              }
      
              public String toString() {
                  return "key: " + k + ' ' + "value: " + v;
              }
          }
      

      你可以打电话

      List<MyObject> myObjectList = map.entrySet().stream().map(MyObject::new).collect(Collectors.toList());
      

      【讨论】:

        【解决方案4】:

        构造函数的问题在于它定义了两个参数,而Stream#map 要求的Function#apply 只接受一个。

        你可以为MyObject写一个静态工厂方法

        class MyObject {
            public static MyObject of(Map.Entry<String, String> e) {
                return new MyObject(e.getKey(), e.getValue());
            }
        }
        

        并像这样引用它

        map(MyObject::of)
        

        在你这样做之前,问问自己,某个地方的普通处理链中的一条漂亮的线是否值得一个新的构造函数或实用程序方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-08-06
          • 1970-01-01
          • 1970-01-01
          • 2018-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多