How to return the correct list type?

If I have a method like this (for simplicity, suppose integers):

public static List<Integer> doSomething(List<Integer> list) { // logic here } 

and I need my processing to create an internally new list, which I will create and somehow fill and return to the caller, how can I do this, since I don’t know what type of list the caller passed?

I do not want to return a List another type that the caller has passed.

eg. If the caller passed a LinkedList and I don't want to return an ArrayList .

How to approach this problem?

+4
source share
5 answers

You should not bind your implementation to a specific implementation of List , the idea of ​​using an interface is that it does not matter from the outside which specific class you create if it corresponds to the List interface.

EDIT:

In any case, it’s possible here:

 List<Integer> lst1 = new ArrayList<Integer>(); Class<?> klass1 = lst1.getClass(); List<Integer> copy1 = (List<Integer>) klass1.newInstance(); System.out.println(copy1.getClass().getName()); > java.util.ArrayList List<Integer> lst2 = new LinkedList<Integer>(); Class<?> klass2 = lst2.getClass(); List<Integer> copy2 = (List<Integer>) klass2.newInstance(); System.out.println(copy2.getClass().getName()); > java.util.LinkedList 

As you can see on the console, copies are instances of the same class as the original list.

+7
source

If you can just use one of these two types of output, you can do

 if (inputList instanceof RandomAccess) { // use an ArrayList } else { // use a LinkedList. } 

The RandomAccess interface means that the implementation allows O (1) get operations.

The token interface used by the List implementation to indicate that they support fast (usually constant) random access. The main purpose of this interface is to allow universal algorithms to change their behavior in order to provide good performance when applied to random or sequential access lists.

In this way, your APIs allow clients to secure their inputs. They can be passed as a result of Collections.unmodifiableList(...) and be sure that it is not modified by other code.

If you really know that the input is a mutable list, you can clone() list and then clear() it. Both ArrayList and LinkedList have public clone() methods that can be accessed reflexively.

+4
source

The best thing to do is remove the list creation from this method. Ask the subscriber to decide how to create a list:

 public static void doSomething(List<Integer> dest, List<Integer> src) { 
+1
source

You can use Class.newInstance to create a list of passed type:

 public static List<Integer> doSomething(List<Integer> list) { List<Integer> newList = null; try { newList = list.getClass().newInstance(); } catch(InstantiationException e) { throw new RuntimeException(e); } catch(IllegalAccessException e) { throw new RuntimeException(e); } //Logic here return newList; } @Test public void test() { List<Integer> testList = new ArrayList<Integer>(); List<Integer> resultList = doSomething(testList); Assert.assertEquals(testList.getClass(), resultList.getClass()); Assert.assertNotSame(LinkedList.class, resultList.getClass()); testList = new LinkedList<Integer>(); resultList = doSomething(testList); Assert.assertEquals(testList.getClass(), resultList.getClass()); Assert.assertNotSame(ArrayList.class, resultList.getClass()); } 
0
source

If you really care about which object comes out, I would include it as a parameter in the method, for example:

 <T extends List<Integer>> T doSomething(Class<T> returnType,List<Integer> v) throws Exception { // constructors for your return will be tricky :) // returnType.newInstance() will probably work. T result = returnType.newInstance(); result.add(86); result.add(99); return result; } 
0
source

Source: https://habr.com/ru/post/1393518/


All Articles