java - 如何将特定算法与流进行转换

标签 java java-stream

任务是返回带有每个字母之和的String。输入也是一个String

例如

input: dasamdw
output: s1d2a2m1w1

我想出了一个简单的快速算法:

private String method(String input) {
    Map<String, Integer> integerMap = new HashMap<>();
    for( char c : input.toCharArray()) {
        String key = String.valueOf(c);
        if(integerMap.containsKey(key)) {
            integerMap.put(key, integerMap.get(key) + 1);
        } else {
            integerMap.put(key, 1);
        }
    }

    StringBuilder sb = new StringBuilder();
    for(Map.Entry<String, Integer> e : integerMap.entrySet()) {
        sb.append(e.getKey());
        sb.append(e.getValue());
    }
    return sb.toString();
}

但我真的很想使用流来实现这一点,例如:

private String method(String input) {
    Map<Character, Integer> collect =
        input.chars().
        mapToObj(i -> (char)i).collect(Collectors.groupingBy(Function.identity(), Collectors.counting() ));

    return collect.entrySet()
                    .stream()
                    .map(entry -> entry.getKey() + "" + entry.getValue())
                    .collect(Collectors.joining(""));
}

但我无法找出正确的 groupingBy 部分...

最佳答案

请注意,甚至您的循环版本也可以简化

private String method(String input) {
    Map<Character, Integer> integerMap = new HashMap<>();
    for(char c: input.toCharArray()) {
        integerMap.merge(c, 1, Integer::sum);
    }

    StringBuilder sb = new StringBuilder();
    for(Map.Entry<Character, Integer> e : integerMap.entrySet()) {
        sb.append(e.getKey()).append(e.getValue());
    }
    return sb.toString();
}

这并不是最糟糕的解决方案。使用 Java 8 并不意味着将所有内容都转换为 Stream API 使用。

您可以使用这样的 Stream 解决方案。

private String method(String input) {
    return input.chars().boxed()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        .entrySet().stream()
        .map(e -> Character.toString((char)e.getKey().intValue())+e.getValue())
        .collect(Collectors.joining());
}

但请注意,最简单的解决方案并不总是最有效的解决方案,例如对于大字符串,以下解决方案可能更可取:

private String method(String input) {
    IntSummaryStatistics ss = input.chars().summaryStatistics();
    int min = ss.getMin();
    int[] counts = new int[ss.getMax()-min+1];
    input.chars().forEach(c -> counts[c-min]++);
    return IntStream.range(0, counts.length)
        .filter(ix -> counts[ix] > 0)
        .collect(StringBuilder::new,
                 (sb,c)->sb.append((char)(c+min)).append(counts[c]),
                 StringBuilder::append)
        .toString();
}

与其他解决方案相比,除了避免开销之外,它还返回本质上排序的结果。

产生排序结果的另一种选择是

private String method(String input) {
    char[] array = input.toCharArray();
    Arrays.sort(array);
    StringBuilder sb = new StringBuilder();
    for(int ix = 0, e; ix<array.length; ix = e) {
        char c = array[ix];
        for(e = ix+1; e<array.length && array[e]==c; ) e++;
        sb.append(c).append(e-ix);
    }
    return sb.toString();
}

关于java - 如何将特定算法与流进行转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47722206/

相关文章:

java - VelocityEngine 不解析模板 [在 struts 中]

java - java中是否有最简单的reduce/fold方法?

java - flatMap Set of Sets inside groupingBy 的优雅方式

java - 如何获取字符串中的数字,然后计算它们的平均值?

Java 8 - 单词计数,然后按降序排列

java - XOM 规范化耗时过长

java - 如何使用 JBOSS Forge API 将父 POM 添加到 POM

java - Mockito 2 + Junit 5 AnnotationSupport.findAnnotation 上的 NoSuchMethodError

java - 如何在 Java 中比较字符串?

java - 学习 Java 8 流