3

I have a class that represents a tree-like structure, the essential bits look like this:

public Node<T> placeAll(Collection<T> elements){    
    for (T e : elements)
        addElement(e);

    // LOG/DEBUG etc
    return root;
}

public void addElement(T el) {
    Node<T> node = new Node<T>(el);
    addElement(root, node);
}

private void addElement(Node<T> parent, Node<T> child) {
    // .... PLACE THE NODE
}

Now this works perfectly fine when I place the nodes one by one in a test case:

public void test() {

    List<Integer> s1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
    // 13 more lists
    List<Integer> s15 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 221, 251); 

    Hypergraph<Object> hg = new Hypergraph<>(...);

        hg.addElement(s1);
        System.out.println(hg.getRoot().toStringTree());
        System.out.println();
              .
              .
              .
        hg.addElement(s15);
        System.out.println(hg.getRoot().toStringTree());
        System.out.println();
    }

If I add the following line hg.placeAll(Arrays.asList(s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15));

to my test case, I get an error regarding the use of generics:

The method placeAll(Collection<Object>) in the type Hypergraph<Object> is not applicable for the arguments (List<List<Integer>>)

I don't quite understand this... If addElement(T el) works fine when I call it with T resolved to List<Integer>, why does List<List<Integer>> comply to placeAll(Collection<T> c)? Considering that List<T> is a Collection<T> I can't make sense out of this..

posdef
  • 6,498
  • 11
  • 46
  • 94
  • @tobias_k it works, but could you explain why that's how it needs to be? if addElement takes T as an argument, placeAll should then be accepting a collection of Ts, intuitively speaking – posdef Feb 06 '15 at 14:32
  • Maybe this helps: http://stackoverflow.com/q/1910892/1639625 – tobias_k Feb 06 '15 at 14:36

1 Answers1

3

The problem is that the method expects a Collection<Object> (as T seems to be Object in your example), but you are passing a Collection<List<Integer>>. And while a List<Integer> is an Object, a Collection<List<Integer>> is not a subclass of a Collection<Object>.

Change the method signature to accept a Collection<? extends T>, then it should work.

public Node<T> placeAll(Collection<? extends T> elements) {   
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • Addendum: Actually, it _should_ work if you do `placeAll(Arrays.asList(...))`, as `asList` should automatically return a collection of the right type. Maybe you actually did `List> foo = Arrays.asList(...); placeAll(foo)`? Or maybe it depends on the Java version. – tobias_k Feb 06 '15 at 14:25
  • Nope, the code is taken directly from the class: `hg.placeAll(Arrays.asList(...);`. On a side note I don't get the point with _And while a `List` is an `Object`, a `Collection>` is not a subclass of a `Collection`._ I get that Collection is not a subclass of Collection, but if X is a subclass of Y, it should still be valid, no? – posdef Feb 06 '15 at 14:27
  • @posdef See it this way: If your method signature was `placeAll(Collection)`, then it would be possible to add an `Object` into the `Collection>` inside the method! With `Collection extends Object>` this is not possible. – tobias_k Feb 06 '15 at 14:39
  • I see, thnx for the additional explanation – posdef Feb 06 '15 at 14:40