使用java流的单词排列

使用java流的单词排列,java,java-8,java-stream,Java,Java 8,Java Stream,我正在尝试生成所有可能的长度为0到4的单词,其中包含字母a到z和a到z。这就是我使用Java stream所得到的 static String[] letters = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); letters[0] = ""; static final int CAPACITY = 1 + 52 + 52*52 + 52*52*52 + 5

我正在尝试生成所有可能的长度为0到4的单词,其中包含字母a到z和a到z。这就是我使用Java stream所得到的

    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)));
但是我想使用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];
}
publicstaticlist-generateWords(int-maxLength,String[]
(信件){
如果(字母长度==0)
返回数组。asList(“”);
int capacity=IntStream.rangeClosed(0,maxLength)
.map(i->(int)Math.pow(letters.length,i))
.sum();
返回IntStream.range(0,容量)
.mapToObj(i->map(i,字母))
.collect(收集器.toCollection(()->新阵列列表(容量));
}
私有静态字符串映射(int索引,字符串[]个字母){
如果(索引==0)返回“”;
返回映射((索引-1)/letters.length,letters)
+字母[(索引-1)%letters.length];
}

谢谢你提出的这个很酷的问题,真是个好问题

需要distinct的原因是空字符串,即长度小于4个字符的单词。例如,
..a
.a.
.a.
a.
都会导致
a
,您需要使用distinct来删除它们。我们应该找到一种方法来解决这个问题,因为“不同”可能意味着大量的比较,这可能会对这些数字产生相当大的影响

防止重复并不难:不要在信件中添加

看看您自己的方法,如果您只对实际字符进行流式处理,并且仅在每个
平面图
之后添加
,您就可以得到您所需要的:

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])));
}
私有静态列表maxWords(int-maxLength,String[]个字母)
{
如果(字母长度==0)
{
返回数组。asList(“”);
}
流s=流的长度(“”);
int[]容量={1};
对于(int i=0;iArrays.Stream(字母).map(word::concat));
容量[0]=容量[0]+(int)数学功率(字母长度,i+1);
}
返回s.collect(Collectors.toCollection(()->new ArrayList(容量[0]));
}

这个备选方案基于Aaron的想法,我更喜欢这个想法。我们首先从0到capacity-1进行枚举,然后将每个数字映射到其对应的字。如果您感兴趣,我强烈建议您观看(第17分钟)以获得解释

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)));
}
私有静态列表maxWords2(int-maxLength,字符串[]个字母)
{
如果(字母长度==0)
{
返回数组。asList(“”);
}
int capacity=IntStream.rangeClosed(0,maxLength)
.map(长度->(int)数学功率(字母.长度,长度))
.sum();
返回IntStream.range(0,容量).mapToObj(i->{
StringBuilder s=新的StringBuilder();
而(i>0)
{
我--;
s、 追加(字母[i%字母.长度]);
i/=字母长度;
}
返回s.reverse().toString();
}).collect(收集器.toCollection(()->新阵列列表(容量));
}

谢谢你提出的这个很酷的问题,真是个好问题

需要distinct的原因是空字符串,即长度小于4个字符的单词。例如,
..a
.a.
.a.
a.
都会导致
a
,您需要使用distinct来删除它们。我们应该找到一种方法来解决这个问题,因为“不同”可能意味着大量的比较,这可能会对这些数字产生相当大的影响

防止重复并不难:不要在信件中添加

看看您自己的方法,如果您只对实际字符进行流式处理,并且仅在每个
平面图
之后添加
,您就可以得到您所需要的:

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])));
}
私有静态列表maxWords(int-maxLength,String[]个字母)
{
如果(字母长度==0)
{
返回数组。asList(“”);
}
流s=流的长度(“”);
int[]容量={1};
对于(int i=0;iArrays.Stream(字母).map(word::concat));
容量[0]=容量[0]+(int)数学功率(字母长度,i+1);
}
返回s.collect(Collectors.toCollection(()->new ArrayList(容量[0]));
}

这个备选方案基于Aaron的想法,我更喜欢这个想法。我们首先从0到capacity-1进行枚举,然后将每个数字映射到其对应的字。如果您感兴趣,我强烈建议您观看(第17分钟)以获得解释

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)));
}
私有静态列表maxWords2(int-maxLength,字符串[]个字母)
{
如果(字母长度==0)
{
返回数组。asList(“”);
}
int capacity=IntStream.rangeClosed(0,maxLength)
.map(长度->(int)数学功率(字母.长度,长度))
.sum();
返回IntStream.range(0,容量).mapToObj(i->{
StringBuilder s=新的StringBuilder();
而(i>0)
{
我--;
s、 追加(字母[i%字母.长度]);
i/=字母长度;
}
返回s.reverse().toString();
}).collect(收集器.toCollection(()->新阵列列表(容量));
}

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

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

希望大家喜欢它