3

I've a method that operates on a List, removing certain duplicates. The algorithm is only efficient on lists implementing RandomAccess. To prevent misuse and disappointing performance, I'm wondering how to enforce the RandomAccess restriction. The RandomAccess interface does not extend List unfortunately, so I sort of need to make the variable be two types at once.

I could declare the method to accept ArrayList rather than List, but other list types can implement RandomAccess too (for example, the lists returned by Collections.synchronizedList and Collections.checkedList), and I don't want to block those.

I tried generics, but couldn't construct a working syntax:

public <T> void process(<List<T> extends RandomAccess> list) {
    ...
}

I could do:

if (!(list instanceof RandomAccess))
    throw new UnsupportedOperationException("RandomAccess list required");

But then the restriction is only enforced at run time, which is less robust.

Help?

Boann
  • 48,794
  • 16
  • 117
  • 146

1 Answers1

5

You need to use multiple bounds, indicated by an ampersand (&):

public <T,L extends List<T> & RandomAccess> void process(L  list)

Putting it into a (non-compilable, unless you remove the second call) class:

public class Main {

    public static void main(String[] argv)
    throws Exception
    {
        Main x = new Main();
        x.process(new ArrayList<String>());
        x.process(new LinkedList<String>());
    }

    public <T,L extends List<T> & RandomAccess> void process(L  list) {

    }
}
parsifal
  • 174
  • 3
  • 1
    To don't have 2 parameters: public static > void process(T list){ – agad Sep 04 '13 at 14:19
  • 1
    @agad - I'm not sure what you're asking. Your example does not apply a bound on the list elements, which is usually important. – parsifal Sep 04 '13 at 14:26
  • I'm not asking, I'm saying, that parametrization by T is not needed; it is enought to parameterize the method with one parameter for simplicity; it doesn't matter, what elements the list contains, it is important, that the argument is random access list. – agad Sep 04 '13 at 14:35
  • Thanks, that's clever. I didn't know that was possible. Unfortunately, it doesn't quite do what I want. It works for `ArrayList`, `Vector`, `Stack`, and so on, but it rejects `Collections.synchronizedList(new ArrayList())`, because although the returned list implements RandomAccess, that isn't specified in the `synchronizedList` method's return type. Is there a solution for that? – Boann Sep 04 '13 at 15:06
  • @Boann - No solution. If you don't have compile-time type information, generics can't help you. – parsifal Sep 04 '13 at 16:38
  • I figured. So this is the right answer to the question I asked, but it's still not something I should do. I'll have to use the run-time `instanceof` test instead. – Boann Sep 04 '13 at 19:03