0

i have task - need to get all combinations of elements in multi-dimensional, different size list`s.

When i put sb initialize in (1) place - i have Error: "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space"

when i put it in (2) - it works faster and without errors.

And i can`t understand why??

public class Combine {

public static void main(String[] args) {

    List<Integer> list1 = new ArrayList<Integer>();
    for (int i = 0; i < 140; i++) {
        list1.add(i);
    }
    List<Integer> list2 = new ArrayList<Integer>();
    for (int i = 200; i < 350; i++) {
        list2.add(i);
    }

    List<Integer> list3 = new ArrayList<Integer>();
    for (int i = 300; i < 350; i++) {
        list3.add(i);
    }

    List<List> list = new ArrayList<List>();
    list.add(list1);
    list.add(list2);
    list.add(list3);
    long startTime = System.currentTimeMillis();
    System.out.println(doCombine(list).size());
    long stopTime = System.currentTimeMillis();
    System.out.println(stopTime - startTime);

}

public static List<String> doCombine(List<List> list) {

    List<String> tempList = new ArrayList<String>();
    List<String> resultList = new ArrayList<String>();

    for (int i = 0; i < list.get(0).size(); i++) {
        resultList.add(String.valueOf(list.get(0).get(i)));
    }

    StringBuilder sb;
    for (int i = 1; i < list.size(); i++) {
        for (String tempItem : resultList) {
(1)         sb = new StringBuilder(tempItem);
            for (int j = 0; j < list.get(i).size(); j++) {
 (2)                   sb = new StringBuilder(tempItem);                     
tempList.add(String.valueOf(sb.append(":").append(list.get(i).get(j))));
                }
            }
            resultList = tempList;
            tempList = new ArrayList<String>();
        }
        return resultList;
    }
    }
  • I suggest that you reduce the number of combinations to generate (say, just have 2 elements in each of `list1`, `list2`, `list3`), and then print the contents of `doCombine(list)` - there is a substantial difference between the two approaches. – Andy Turner Jun 07 '16 at 07:35
  • In place (1) you accumulate more data in `sb` so you need more heap. – gdros Jun 07 '16 at 08:07
  • thanks guys, now i see, sb append and append again in "j" cycle – Dmitriy Polovinkin Jun 07 '16 at 08:10
  • Do you think `String.valueOf(sb.append(…))` is in any way better than a simple `sb.append(…).toString()`? Besides that, it’s a great example of how a simple `tempList.add(tempItem+":"+list.get(i).get(j));` would lead to the more efficient solution, preventing the errors you can make with your manual `StringBuilder` code… – Holger Jun 07 '16 at 18:05
  • @Holger, well, StringBuilder is faster, that's why he is there. And S.valueOf is just for null pointer case. – Dmitriy Polovinkin Jun 08 '16 at 06:39
  • There is no sense in protecting against an impossible null pointer case. The `StringBuilder` instance is never `null`. Besides that, the source code `tempItem+":"+list.get(i).get(j)` gets compiled to either `new StringBuilder(tempItem).append(":").append(list.get(i).get(j)).toString()` or `new StringBuilder().append(tempItem).append(":").append(list.get(i).get(j)).toString()`, depending on the compiler. As you can see, the result is equivalent or even identical to your faster variant, just simpler to write. You obviously never compared the speed but just claim “StringBuilder is faster”… – Holger Jun 08 '16 at 09:02
  • About 'just claim SB is faster'- look at code, i'm output run time. And if you replace StringBuilder by String, you will see the difference. – Dmitriy Polovinkin Jun 08 '16 at 20:57

0 Answers0