如何使用流转换特定算法

时间:2017-12-08 21:12:34

标签: java java-stream

任务是以每个字母的总和返回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

但我无法找出正确的$array1 = [ '12345', '23457' ]; $array2 = [ ['id' => '12345', 'fake_data' => 'something'], ['id' => '23457', 'more_data' => 'something else'], ['id' => '76389','more_data' => 'something else 3'], ['id' => '10293', 'more_data' => 'something else 4'], ['id' => '09229', 'more_data' => 'something else 5'] ]; $found_id_rows = array_filter($array2, function($row) use($array1) { return in_array($row['id'], $array1); }); $not_found_id_rows = array_filter($array2, function($row) use($array1) { return !in_array($row['id'], $array1); }); 部分......

4 个答案:

答案 0 :(得分:0)

Collectors.counting()返回时,您需要更改地图目标类型:

Map<Character, Integer> collect

Map<Character, Long> collect

除此之外,您可以合并groupingByjoining  收集者使用Collectors.collectingAndThen,即:

return Arrays.stream(input.split(""))
             .collect(
                 collectingAndThen(groupingBy(identity(), counting()), 
                         e -> e.entrySet()
                               .stream()
                               .map(entry -> entry.getKey() + entry.getValue())
                               .collect(joining())));

确保使用导入:

import static java.util.stream.Collectors.*;
import static java.util.function.Function.*;

答案 1 :(得分:0)

String foo = "dasamdw";
Arrays.stream(foo.split(""))
          .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
          .entrySet().stream()
                     .map(entry -> entry.getKey() + entry.getValue())
                     .collect(Collectors.joining(""));

这给出了结果 - &gt; a2s1d2w1m1

您可以根据需要添加排序方式。

答案 2 :(得分:0)

这是我的版本,我添加了一些评论,以便您可以轻松获得:

import { ..., ApplicationRef } from '@angular/core'
...

export class App {
  ...
  constructor(private applicationRef: ApplicationRef) {
    ...
  }
  setValue() {
    console.log(this.childComponent.prop);
    this.propValue = "button clicked";
    this.applicationRef.tick(); // Trigger change detection
    console.log(this.childComponent.prop);
  }
}

您也可以用Merge

替换三元组

答案 3 :(得分:0)

请注意,即使您的循环版本也可以简化

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();
}