【问题标题】:Java - Permutation of objects in Arraylist within an ArraylistJava - Arraylist 中 Arraylist 中对象的排列
【发布时间】:2018-08-07 04:29:38
【问题描述】:

我是 Java 和 Stack Overflow 的新手,我有一个关于排列的问题。

方法:我使用ArrayList 中的对象生成ArrayList。每个ArrayList 的大小从1(最小1 可能)到infinite,并包含具有唯一名称属性的自定义生成对象。

问题: 现在我的问题是如何获得从第一个 ArrayList 到最后一个ArrayList 的所有可能对象组合的排列(我想我们可以说这是 x-轴)在我的外部ArrayList(y 轴)内?

示例: 我试着画一个简单的例子:

  1. ArrayList: 1.1 | 1.2 | 1.3
  2. ArrayList:2.1
  3. ArrayList: 3.1 | 3.2

这里这些ArrayLists 在外部ArrayList 中(因为未知数量的可能ArrayLists 带有对象)。第二个数字是显示不同的对象。假设“让所有可能的组合从上到下”。

结果: 我想得到一个看起来像这样的结果:

  1. 组合:1.1 | 2.1 | 3.1
  2. 组合:1.1 | 2.1 | 3.2
  3. 组合:1.2 | 2.1 | 3.1
  4. 组合:1.2 | 2.1 | 3.2
  5. 组合:1.3 | 2.1 | 3.1
  6. 组合:1.3 | 2.1 | 3.2

编辑:这里是分隔符“|”代表例如ArrayList 中的一个槽。这些组合不应该写在控制台中,因为我需要单独访问排列的每个对象。

最好的情况是如果我可以一个接一个地获得每个组合,因为我想检查每个组合的几个条件,并且只在进一步的 ArrayList 或 .txt 文件中保护某些组合。

到目前为止我得到了什么: 我找到了一个代码 sn-p,它在 ArrayList 内将 ArrayListsStrings 置换,并返回一个 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 这个名称来取回对象。

问题: 此方法仅适用于ArrayList 中的少数ArrayLists(例如,如上面的示例)。如果有例如16 个ArrayLists 在外部ArrayList 中的大小为7,我得到"MemoryOutOfSpace" 的错误。

如前所述,最好的情况是在组合后获得组合,并单独决定是否要保留组合(我想我会将每个组合保存在 .txt 文件中,因为它可能是我想要的保留每一个组合 --> 绕过另一个"MemoryOutOfSpace"-Error 的问题。

简短摘要: 内部-ArrayLists 带有对象(大小从 1 到未知大小)。 外部-ArrayList 和内部-ArrayLists(大小未知)。 想要的输出:从上到下的所有对象组合。

提前致谢。

【问题讨论】:

    标签: java object arraylist permutation


    【解决方案1】:

    //编辑:我理解错了问题。这不是正确的解决方案。


    据我了解您的问题,您只需要遍历所有三个列表,获取所有元素并将它们添加在一起。

    这是一个简单的示例,其中包含 3 个字符串类型列表以及您给定的示例:

    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
    

    【讨论】:

    • 感谢您的回答,但这并不是我想要的。如上所述,我不知道外部 ArrayList 中 ArrayList 的数量。我编辑了我的问题
    • 啊抱歉,那我没理解你的问题 :) 很高兴你得到了答案!
    【解决方案2】:

    我认为您问题的关键字是笛卡尔积而不是排列。你可以试试这样的:

    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)

    Cartesian product of arbitrary sets in Java

    【讨论】:

    • 非常感谢@Eritrean。这种方法适用于我想要的解决方案。我已经用大量(约 30 个)大小从 1 到 6 的数组列表对其进行了测试,并将解决方案写在一个 txt 文件中,并在运行 0.5 小时后(我在那段时间之后中止)得到一个超过1 GB 空间:D
    【解决方案3】:

    我认为您必须递归地执行此操作。在 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方法,它不是最干净的代码……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      • 2017-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 1970-01-01
      相关资源
      最近更新 更多