使用java流排列单词

时间:2017-05-03 09:37:01

标签: java java-8 java-stream

我试图用字母a到z和A到Z来生成长度为0到4的所有可能的单词。这就是我使用Java流的方法

    static String[] letters
            = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
    letters[0] = "";

    static final int CAPACITY = 1 + 52 + 52*52 + 52*52*52 + 52*52*52*52;

    static List<String> words
        = Arrays.stream(LETTERS)
            .flatMap(word -> Arrays.stream(LETTERS).map(word::concat))
            .flatMap(word -> Arrays.stream(LETTERS).map(word::concat))
            .flatMap(word -> Arrays.stream(LETTERS).map(word::concat))
            .distinct()
            .collect(Collectors.toCollection(() -> new ArrayList<>(CAPACITY)));

还有其他解决方案,我不必使用distinct()吗?我知道我可以这样做:

    String[] letters
            = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
    List<String> words = new ArrayList<>();
    words.add("");
    for(String letter1 : letters) {
        words.add(letter1);
        for(String letter2 : letters) {
            words.add(letter1 + letter2)
            for(String letter3 : letters) {
                words.add(letter1 + letter2 + letter3);
                for(String letter4 : letters) {
                    words.add(letter1 + letter2 + letter3 + letter4);
                }
            }
        }
    }

但我想用Java流做。

(编辑) 在你的建议之后:

public static List<String> generateWords(int maxLength, String[] 
    letters) {
    if (letters.length == 0)
        return Arrays.asList("");

    int capacity = IntStream.rangeClosed(0, maxLength)
            .map(i -> (int) Math.pow(letters.length, i))
            .sum();

    return IntStream.range(0, capacity)
            .mapToObj(i -> map(i, letters))
            .collect(Collectors.toCollection(() -> new ArrayList<>(capacity)));
}

private static String map(int index, String[] letters) {
    if(index == 0) return "";
    return map((index - 1) / letters.length, letters)
            + letters[(index - 1) % letters.length];
}

2 个答案:

答案 0 :(得分:1)

感谢这个很酷的问题,非常好!

您需要distinct的原因是空字符串,即长度小于4个字符的单词。例如,.a..a...a""都会生成"",您需要使用distinct来删除它们。我们应该找到解决方法,因为明显可能意味着很多的比较,这可能会对这些数字产生相当大的影响。

防止创建重复项并不困难:不要在信件中添加flatMap

查看您自己的方法,如果您只对实际字符进行流式处理,并且仅在每个Condsider letters = {a, b}, maxLength = 2 Start with Stream.of("") 1st flatMap: [a, b] add "": [, a, b] 2nd flatMap: [a, b, aa, ab, ba, bb] add "": [, a, b, aa, ab, ba, bb] 之后添加private static List<String> maxWords(int maxLength, String[] letters) { if (letters.length == 0) { return Arrays.asList(""); } Stream<String> s = Stream.of(""); int[] capacity = { 1 }; for (int i = 0; i < maxLength; i++) { s = Stream.concat(Stream.of(""), s.flatMap(word -> Arrays.stream(letters).map(word::concat))); capacity[0] = capacity[0] + (int) Math.pow(letters.length, i + 1); } return s.collect(Collectors.toCollection(() -> new ArrayList<>(capacity[0]))); } ,那么您将获得所需内容:

private static List<String> maxWords2(int maxLength, String[] letters)
{
    if (letters.length == 0)
    {
        return Arrays.asList("");
    }

    int capacity = IntStream.rangeClosed(0, maxLength)
                            .map(length -> (int) Math.pow(letters.length, length))
                            .sum();

    return IntStream.range(0, capacity).mapToObj(i -> {
        StringBuilder s = new StringBuilder();
        while (i > 0)
        {
            i--;
            s.append(letters[i % letters.length]);
            i /= letters.length;
        }
        return s.reverse().toString();
    }).collect(Collectors.toCollection(() -> new ArrayList<>(capacity)));
}

这是一个很好的方法:

{{1}}

此替代方案基于Aaron的想法,我更喜欢它。我们首先从0枚举到capacity-1,然后将每个数字映射到其对应的单词。如果您有兴趣,我强烈建议您观看this video about the Library of Babel(从第17分钟开始)获取解释。

{{1}}

答案 1 :(得分:0)

我参加聚会有点晚了,因为几天前我刚刚了解了 Java 8 流和 lambda。不管怎样,我看到你的问题,我决定试一试。

我的解决方案涉及将流流水线与递归结合使用。我喜欢流的一个方面是您可以将它们链接在一起。这就是递归调用它们来解决排列问题的想法的来源。

希望你们喜欢它,并可以给我一些改进方法的想法。

编辑:感谢匿名用户提出的改进建议。现在考虑 r = 1。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class RecursivePermutation {


    // Returns a stream of permutations of c.size()
    // elements taken r at a time without repetition.
    // Example: If  C={1,2} and r=2
    //      Output:  {(1,2), (2,1)}
    // This recursive function uses the chain property of streams
    public static <T> Stream<List<T>> permutations(List<T> c, int r){
        if (r==1){
            return c.stream()
                    .map(e -> Arrays.asList(e));
        } else
        if (r==2){
            return c.stream()
                    .flatMap(
                            e1 -> c.stream()  // e1: refers to an element of c
                                    .filter(e2 -> !e1.equals(e2)) // e2: refers to an element of c
                                    .map(e2 -> Arrays.asList(e1, e2))
                    );
        } else {
            return permutations(c, r-1)
                    .flatMap(
                            l -> c.stream()
                                    .filter( e -> l.contains(e) == false)
                                    .map(e -> {
                                        List<T> out = new ArrayList<>();
                                        out.addAll(l);
                                        out.add(e);
                                        return out;}
                                    )
                    );
        }
    }

    public static void main(String[] args) {

        // Name Permutations
        List<String> stringList = Arrays.asList("Joe", "Ana", "Pete", "Mark", "Lucy");
        List<List<String>> sp =
                permutations(stringList, 2).collect(Collectors.toList());
        System.out.println(sp);

        // Integers Permutations
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
        List<List<Integer>> np =
                permutations(numbers, 3).collect(Collectors.toList());
        System.out.println(np);

    }

}

运行此代码将为您提供以下输出:

[[Joe, Ana], [Joe, Pete], [Joe, Mark], [Joe, Lucy], [Ana, Joe], [Ana, Pete], [Ana, Mark], [Ana, Lucy], [Pete, Joe], [Pete, Ana], [Pete, Mark], [Pete, Lucy], [Mark, Joe], [Mark, Ana], [Mark, Pete], [Mark, Lucy], [Lucy, Joe], [Lucy, Ana], [Lucy, Pete], [Lucy, Mark]]

[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 2, 6], [1, 2, 7], [1, 3, 2], [1, 3, 4], [1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 2], [1, 4, 3], [1, 4, 5], [1, 4, 6], [1, 4, 7], [1, 5, 2], [1, 5, 3], [1, 5, 4], [1, 5, 6], [1, 5, 7], [1, 6, 2], [1, 6, 3], [1, 6, 4], [1, 6, 5], [1, 6, 7], [1, 7, 2], [1, 7, 3], [1, 7, 4], [1, 7, 5], [1, 7, 6], [2, 1, 3], [2, 1, 4], [2, 1, 5], [2, 1, 6], [2, 1, 7], [2, 3, 1], [2, 3, 4], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 1], [2, 4, 3], [2, 4, 5], [2, 4, 6], [2, 4, 7], [2, 5, 1], [2, 5, 3], [2, 5, 4], [2, 5, 6], [2, 5, 7], [2, 6, 1], [2, 6, 3], [2, 6, 4], [2, 6, 5], [2, 6, 7], [2, 7, 1], [2, 7, 3], [2, 7, 4], [2, 7, 5], [2, 7, 6], [3, 1, 2], [3, 1, 4], [3, 1, 5], [3, 1, 6], [3, 1, 7], [3, 2, 1], [3, 2, 4], [3, 2, 5], [3, 2, 6], [3, 2, 7], [3, 4, 1], [3, 4, 2], [3, 4, 5], [3, 4, 6], [3, 4, 7], [3, 5, 1], [3, 5, 2], [3, 5, 4], [3, 5, 6], [3, 5, 7], [3, 6, 1], [3, 6, 2], [3, 6, 4], [3, 6, 5], [3, 6, 7], [3, 7, 1], [3, 7, 2], [3, 7, 4], [3, 7, 5], [3, 7, 6], [4, 1, 2], [4, 1, 3], [4, 1, 5], [4, 1, 6], [4, 1, 7], [4, 2, 1], [4, 2, 3], [4, 2, 5], [4, 2, 6], [4, 2, 7], [4, 3, 1], [4, 3, 2], [4, 3, 5], [4, 3, 6], [4, 3, 7], [4, 5, 1], [4, 5, 2], [4, 5, 3], [4, 5, 6], [4, 5, 7], [4, 6, 1], [4, 6, 2], [4, 6, 3], [4, 6, 5], [4, 6, 7], [4, 7, 1], [4, 7, 2], [4, 7, 3], [4, 7, 5], [4, 7, 6], [5, 1, 2], [5, 1, 3], [5, 1, 4], [5, 1, 6], [5, 1, 7], [5, 2, 1], [5, 2, 3], [5, 2, 4], [5, 2, 6], [5, 2, 7], [5, 3, 1], [5, 3, 2], [5, 3, 4], [5, 3, 6], [5, 3, 7], [5, 4, 1], [5, 4, 2], [5, 4, 3], [5, 4, 6], [5, 4, 7], [5, 6, 1], [5, 6, 2], [5, 6, 3], [5, 6, 4], [5, 6, 7], [5, 7, 1], [5, 7, 2], [5, 7, 3], [5, 7, 4], [5, 7, 6], [6, 1, 2], [6, 1, 3], [6, 1, 4], [6, 1, 5], [6, 1, 7], [6, 2, 1], [6, 2, 3], [6, 2, 4], [6, 2, 5], [6, 2, 7], [6, 3, 1], [6, 3, 2], [6, 3, 4], [6, 3, 5], [6, 3, 7], [6, 4, 1], [6, 4, 2], [6, 4, 3], [6, 4, 5], [6, 4, 7], [6, 5, 1], [6, 5, 2], [6, 5, 3], [6, 5, 4], [6, 5, 7], [6, 7, 1], [6, 7, 2], [6, 7, 3], [6, 7, 4], [6, 7, 5], [7, 1, 2], [7, 1, 3], [7, 1, 4], [7, 1, 5], [7, 1, 6], [7, 2, 1], [7, 2, 3], [7, 2, 4], [7, 2, 5], [7, 2, 6], [7, 3, 1], [7, 3, 2], [7, 3, 4], [7, 3, 5], [7, 3, 6], [7, 4, 1], [7, 4, 2], [7, 4, 3], [7, 4, 5], [7, 4, 6], [7, 5, 1], [7, 5, 2], [7, 5, 3], [7, 5, 4], [7, 5, 6], [7, 6, 1], [7, 6, 2], [7, 6, 3], [7, 6, 4], [7, 6, 5]]