简体   繁体   中英

difference new LinkedList<>(new LinkedList<>()) and new LinkedList…, add

Update: Thanks for all the answers. The cleanest solution I've found is this one:

if ( k<=0 ) return new LinkedList<>(Arrays.asList(new LinkedList<>()));

I'have a recursive method that generates all the 'n choose k' combinations from a list. In the implementation I've found that there is a curious difference between two ways of creating new LinkedList instances.

public static <T> List<List<T>> extract2(int k, List<T> list) {
    if ( k<=0 ) {
        // this way fails the test
        return new LinkedList<>(new LinkedList<>());
        // and this way works fine.
        //var v = new LinkedList<List<T>>();
        //v.add(new LinkedList<>());
        //return v;
    }

    if ( list.isEmpty())
        return new LinkedList<>();

    T h = list.get(0);
    List<T> tl = new LinkedList<>(list.subList(1, list.size()));

    List<List<T>> with_h = extract2(k - 1, tl).stream()
            .peek(l -> l.add(0, h)).collect(Collectors.toList());
    List<List<T>> without_h = extract2(k, tl);
    with_h.addAll(without_h);
    return with_h;
}

The code works fine with the commented-out initialization of the LinkedList, but with the new LinkedList(new LinkedList()) it fails.

Am I running into some sort of compiler optimization?

Here's a small Junit5 test

        var res = App.extract2(2, Arrays.asList("a", "b", "c", "d"));
        assertThat(res, is(Arrays.asList(
                Arrays.asList("a", "b"),
                Arrays.asList("a", "c"),
                Arrays.asList("a", "d"),
                Arrays.asList("b", "c"),
                Arrays.asList("b", "d"),
                Arrays.asList("c", "d")

        )));

Here

new LinkedList<>(new LinkedList<>());

You are using a LinkedList constructor which takes elements from parameter collection and adds them to this LinkedList. It is totally different from creating a LinkedList and adding a new LinkedList as element to it, using add() method.

new LinkedList<>(new LinkedList<>())

creates a new LinkedList and adds all items out of the List handed to the constructor as items to it. The handed List is empty so your returned List is also empty.

var v = new LinkedList<List<T>>();
v.add(new LinkedList<>());

creates an empty List then adds an empty List as item to it. So the first List has now one entry.

The difference is that in the first example you create just an empty list and the second creates a list with an item of an (empty) list. This results in a difference in your algorithm.

Thanks all and especially @Simulant for the clear answer! JShell should have woken me up:

jshell> new LinkedList(new LinkedList());
$5 ==> []

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM