返回字母所在字符串的总和 - 使用流

时间:2017-02-08 09:09:28

标签: java java-stream

我有一个单词列表(编程语言),我想弄清楚这些单词中字母表中的哪个字母,然后将这些单词的总字符串长度相加,最后返回一个字母返回与这些单词匹配的最长字符串。这是我到现在为止所得到的,而且我几乎没有进一步发展。

这是我尝试更好地理解java流的练习。

package com.example;

import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class DemoApplicationTests {

    @Test
    public void argh() {

        List<String> list = new ArrayList<>();
        list.add("java");
        list.add("php");
        list.add("python");
        list.add("perl");
        list.add("c");
        list.add("lisp");
        list.add("c#");

        Supplier<Stream<String>> streamSupplier = () -> list.stream();
        IntStream.range('a', 'z').forEach(i -> {
                int strlen = streamSupplier.get()
                    .filter(k -> {
                            char ch = (char) i;
                            return k.contains("" + ch);
                        }
                    )
                    .map(s -> s.length())
                    .mapToInt(Integer::new)
                    .sum();
                System.out.println((char) i + " : " + strlen);
            }
        );
   }
}

我期望的最终输出(结果)就像是 “p:17”

由于字符'p'出现在单词php,python,perl,lisp中,它将这些单词相加并返回stringlength为17。

最好是

map<String,int> with the size of 1

或其他东西,只包含最长的字符串。

这里有一些伪代码,关于我如何在'普通'java中编写它:

int previousSum = 0;
for (string ch in ('a' to 'z') ) {
    int stringlengthSum =     findallMatchesInListandSumStringlength(stringlist,ch);
if (stringlengthSum > previousSum) {
    previousSum = stringLengthSum;
    longestCharacter = ch;
}
}
System.out.println("The longest sum is: " + previousSum + " by the character: " + longestcharacter);

2 个答案:

答案 0 :(得分:1)

我不得不稍微改变并优化您的代码。最终解决方案将是:

Map.Entry<Integer, Integer> max = IntStream.range('a', 'z').boxed().collect(Collectors.toMap(i -> i, i -> list.stream()
        .filter(k -> k.contains("" + (char) i.intValue()))
        .map(String::length)
        .mapToInt(Integer::new)
        .sum()))
        .entrySet().stream()
        .max((e1, e2) -> e1.getValue().compareTo(e2.getValue())).get();

System.out.println((char)max.getKey().intValue() + ":" + max.getValue()); 

变更是:

1)将IntStream转换为Stream<Integer>以便能够从中收集地图

2)收集对:符号的int值 - &gt;带有此符号的单词总和

并且至少3)找到其中包含最大元素的地图条目

答案 1 :(得分:1)

你非常接近,你基本上只是错过了流的排序。

为了使整个订单更容易,您可以创建一个专用类:

class CharacterLengthSumResult implements Comparable<CharacterLengthSumResult> {
        final char c;
        final int sum;

        CharacterLengthSumResult(char c, int sum) {
            this.c = c;
            this.sum = sum;
        }

        @Override
        public int compareTo(CharacterLengthSumResult o) {
            return Integer.compare(o.sum, sum);
        }
    }

然后流逻辑成为:

Optional<CharacterLengthSumResult> first = IntStream.range('a', 'z').mapToObj(i -> {
            String c = ((char) i) + "";
            int sum = list.stream().filter(s -> s.contains(c)).mapToInt(String::length).sum();
            return new CharacterLengthSumResult((char)i, sum);
        }).sorted().findFirst();

        if (first.isPresent()) {
            System.out.println(first.get().c + " -> " + first.get().sum);
        }

如果您想将整个事物作为地图,您可以使用收集器扩展已排序的内容:

...sorted().collect(Collectors.toMap(s -> s.c, s -> s.sum));