我是Java和Stack Overflow的新手,我对排列有疑问。
方法:我用ArrayList
中的对象生成ArrayList
。每个ArrayList
的大小从1
(可能的minium 1)到infinite
,并包含具有唯一名称属性的自定义生成对象。
问:现在我的问题是我如何在我的外部ArrayList
(y轴)内得到所有可能的对象组合的排列,从第一个ArrayList
到lastArrayList
(我想我们可以说这是x轴)?
示例:我尝试绘制一个简单示例:
ArrayList
1.1 | 1.2 | 1.3ArrayList
:2.1ArrayList
3.1 | 3.2这里的ArrayLists
在外部ArrayList
(因为可能的ArrayLists
与物体的未知数量)。第二个数字是显示不同的对象。让我们说“让每一种可能的组合从上到下”。
结果:我想得到一个如下所示的结果:
编辑:这里的分隔符“|”代表例如ArrayList中的一个槽。组合不应该在控制台中写入,因为我需要单独访问排列的每个对象。
最好的情况是,如果我可以在另一个组合之后获得每个组合,因为我想检查每个组合的几个条件,并且只在另一个ArrayList
或.txt文件中安全某些组合。
到目前为止我所得到的:我找到了一个代码片段,它在ArrayLists
中用Strings
置换ArrayList
并返回单个ArrayList
与Strings
组合。
public static ArrayList<String> combineAllCases(ArrayList<ArrayList<String>> totalList)
{
ArrayList<String> result = new ArrayList<String>(totalList.get(0));
for(int index = 1; index < totalList.size() ; index++)
{
result = (ArrayList<String>) combineTwoLists(result, totalList.get(index));
}
return result;
}
和
private static ArrayList<String> combineTwoLists(ArrayList<String> list1, ArrayList<String> list2)
{
ArrayList<String> result = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
for(String s1 : list1)
{
for(String s2: list2)
{
sb.setLength(0);
sb.append(s1).append("#").append(s2);
result.add(sb.toString());
}
}
return result;
}
想法:使用这种方法,我可以使用String
拆分来获得每个组合的每个对象名称,并可以搜索此名称旧的ArrayLists
以获取对象。
问题:此方法仅适用于ArrayLists
中的少量ArrayList
(例如,如上例所示)。如果有例如16 ArrayLists
在外面的ArrayList
大小为7,我得到"MemoryOutOfSpace"
的错误。
因此,最好的情况是在组合后获得组合并单独决定是否要保留组合(我想我会将每个组合保存在.txt文件中,因为它可能是,我想保留每一个组合 - >绕过"MemoryOutOfSpace"
的另一个问题 - 错误)。
简短摘要:内部ArrayLists
与对象(大小从1到未知大小)。外ArrayList
与内部ArrayLists
(未知大小)。通缉输出:从上到下的每个物体组合。
提前致谢。
我认为你问题的关键词是笛卡儿积,而不是排列。你可以尝试这样的事情:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.stream.Stream;
class Test{
public static void main(String[] args){
List<List<String>> totalList = new ArrayList<>();
totalList.add(Arrays.asList("1.1","1.2","1.3"));
totalList.add(Arrays.asList("2.1"));
totalList.add(Arrays.asList("3.1","3.2"));
Supplier<Stream<String>>[] sup = new Supplier[totalList.size()];
for(int i = 0; i<totalList.size();i++){
final int j = i;
sup[i]= () -> totalList.get(j).stream();
}
Stream<String> result = cartesian((a, b) -> a+"|"+b, sup);
result.forEach(System.out::println);
}
private static <T> Stream<T> cartesian(BinaryOperator<T> aggregator, Supplier<Stream<T>>... streams) {
return Arrays.stream(streams)
.reduce((s1, s2) ->
() -> s1.get().flatMap(t1 -> s2.get().map(t2 -> aggregator.apply(t1, t2))))
.orElse(Stream::empty).get();
}
}
有关更多信息,请参阅其他SO问题:Cartesian product of streams in Java 8 as stream (using streams only)
我认为你必须递归地做。也许可以在Java 8中使用流,但我还不熟悉它们。所以这是使用递归的样子:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class ArrayLists {
ArrayList<List<String>> outer = new ArrayList(5);
List<String> helper = new ArrayList<String>();
public static void main(String[] args) {
ArrayLists arrayLists = new ArrayLists();
arrayLists.displayPermutations();
}
private void displayPermutations() {
List<String> l1 = new ArrayList<String>();
l1.add("1.1");
l1.add("1.2");
l1.add("1.3");
List<String> l2 = new ArrayList<String>();
l2.add("2.1");
l2.add("2.2");
List<String> l3 = new ArrayList<String>();
l3.add("3.1");
l3.add("3.2");
l3.add("3.3");
outer.add(l1);
outer.add(l2);
outer.add(l3);
initHelper();
recursion(l1);
}
private void initHelper() {
for(int i = 0; i < outer.size(); i++) {
helper.add(i, outer.get(i).get(0));
}
}
void recursion(List<String> listToIncrement) {
int helperIndex = outer.indexOf(listToIncrement);
for(int i = 0; i < listToIncrement.size(); i++) {
helper.set(helperIndex, listToIncrement.get(i));
if(helperIndex < outer.size() - 1) {
recursion(outer.get(helperIndex + 1));
}
else{
System.out.println(helper);
}
}
}
}
当然,你可以摆脱initHelper方法,它不是最干净的代码......
//编辑:我理解错误的问题。这不是一个正确的解决方案。
据我了解你的问题,你只需要遍历所有三个列表,获取所有元素并将它们加在一起。
下面是一个简单的示例,其中包含3个String类型列表以及给定的示例:
List<String> l1 = new ArrayList<String>();
l1.add("1.1");
l1.add("1.2");
l1.add("1.3");
List<String> l2 = new ArrayList<String>();
l2.add("2.1");
List<String> l3 = new ArrayList<String>();
l3.add("3.1");
l3.add("3.2");
for (String s1 : l1)
{
for (String s2 : l2)
{
for (String s3 : l3)
{
System.out.println(s1 + " | " + s2 + " | " + s3);
}
}
}
打印
1.1 | 2.1 | 3.1
1.1 | 2.1 | 3.2
1.2 | 2.1 | 3.1
1.2 | 2.1 | 3.2
1.3 | 2.1 | 3.1
1.3 | 2.1 | 3.2
它的作用非常简单:首先,我们用你想要创建排列的值填充我们的三个数组。
然后我们真的可以读取代码:For every String s1 in the list l1 we take every String s2 in l2. For those combinations we take every string s3 in l3. Then we print out the combination
所以内部做的是:
s1 | s2 | s3
1.1 | |
1.1 | 2.1 |
1.1 | 2.1 | 3.1 -> print
1.1 | 2.1 | 3.2 -> print
1.2 | |
1.2 | 2.1 | 3.1 -> print
1.2 | 2.1 | 3.2 -> print
1.3 | |
1.3 | 2.1 | 3.1 -> print
1.3 | 2.1 | 3.2 -> print