【问题标题】:Functional solution to reconstruct Map from String从 String 重构 Map 的功能解决方案
【发布时间】:2016-08-30 20:51:21
【问题描述】:

我一直在环顾四周,但无法使用 Java 8 提出一个优雅的功能解决方案。这是我要解决的问题:

例如,我已将映射“序列化”为单个字符串

{ type  -> 'fruit',
  color -> 'yellow',
  age   -> 5 }

会变成:

type:fruit;color:yellow;age:5

现在,我想从字符串重新创建原始地图

Arrays.stream(input.split(";"))
        .map(v -> v.split(":"))
        .collect(Collectors.toMap(c -> c[0], c -> c.[1]);

请注意,如果列表中没有“:”,上面的代码将导致NullPointerException,这可以通过以下方式解决:

c.length > 1 ? c[1] : c[0]

但这感觉不对。有任何使用 Java8 API 的建议或替代方案吗?

【问题讨论】:

  • 如果值中有;: 怎么办?

标签: java lambda functional-programming java-8


【解决方案1】:

这对我有用:

class StreamToInflateStringToMap {
    private static Function<String, String> keyMapper =
            s -> s.substring(0, s.indexOf(":"));
    private static Function<String, String> valueMapper =
            s -> s.substring(s.indexOf(":") + 1);

    public static Map<String, String> inflateStringToMap(String flatString) {
        return Stream.of(flatString.split(";")).
                collect(Collectors.toMap(keyMapper, valueMapper));
    }

    public static void main(String[] args) {
        String flatString = "type:fruit;color:yellow;age:5";
        System.out.println("Flat String:\n" + flatString);
        Map<String, String> inflatedMap = inflateStringToMap(flatString);
        System.out.println("Inflated Map:\n" + inflatedMap);
    }
}

请注意,我假设您的意思是您想要一个解决分号丢失时的解决方案(即:地图中只有一个项目)。如果没有冒号,那么抛出异常是完全正确的,因为这意味着字符串中没有定义映射,并且必须将错误的值传递给方法。

Alexey Romanov 提出的评论也是有效的:你能保证在内容中不会找到分隔符作为实际键/值字符串的一部分吗?如果不是,那么您将遇到麻烦(无论您使用何种膨胀方法),因此可能需要验证放入地图原始副本中的值。

还请注意,我已将 Function&lt;String, String&gt; 映射器声明为该类的静态成员,但如果您永远不需要在其他任何地方使用它们并且您认为它不会使代码太丑了。

此外,通过 Java 8 API 的一些探索发现了另一种方法,可以从分隔符分隔的 String 创建 Stream。您可以使用Pattern.splitAsStream(CharSequence) 方法,如下所示:

private static final Pattern SINGLE_SEMICOLON = Pattern.compile(";");

public static Map<String, String> inflateStringToMap(String flatString) {
    return SINGLE_SEMICOLON.splitAsStream(flatString).
            collect(Collectors.toMap(keyMapper, valueMapper));
}

(注意warning in the API 将可变的CharSequence 类型(例如StringBuilder)提供给splitAsStream 方法。)

【讨论】:

    【解决方案2】:

    如果你有番石榴,你可以使用

    Splitter.on(';').withKeyValueSeparator(':').split(input)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 2011-12-24
      相关资源
      最近更新 更多