如何返回正确的列表类型?

时间:2012-01-28 15:54:23

标签: java list arraylist linked-list

如果我有这样的方法(为简单起见假设整数):

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

我需要我的处理内部创建一个新列表我将创建并以某种方式填充并返回给调用者,我怎么能这样做,因为我不知道什么类型的列表来电者传了?

我不想返回调用者传入的不同类型的List

E.g。如果来电者通过LinkedList并且我 想要返回ArrayList

如何最好地解决这个问题?

5 个答案:

答案 0 :(得分:7)

你不应该将你的实现绑定到List的特定实现,使用接口的想法是,从外部来看,只要它实例化的具体类就不重要了符合List接口。

编辑:

无论如何,这是一种可能的方式:

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

正如您在控制台中看到的,副本是与原始列表相同的类的实例。

答案 1 :(得分:4)

如果您只是使用这两种输出类型中的一种,那么就可以

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

RandomAccess接口用于表示实现允许O(1)get操作。

  

List实现使用的标记接口,表示它们支持快速(通常是恒定时间)随机访问。此接口的主要目的是允许通用算法更改其行为,以便在应用于随机或顺序访问列表时提供良好的性能。

通过这样做,您的API允许客户端保护他们的输入。他们可以传递Collections.unmodifiableList(...)的结果,并确保它不会被其他代码修改。

如果您确实知道输入是可变列表,则可以clone()列表,然后clear()ArrayListLinkedList都有公共clone()方法,可以反复访问。

答案 2 :(得分:1)

最好的办法是从方法中删除列表创建。让调用者决定如何创建列表:

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

答案 3 :(得分:0)

您可以使用Class.newInstance创建传入类型的列表:

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());       
}

答案 4 :(得分:0)

如果你真的非常关心会出现什么样的对象,我会将其作为参数包含在方法中,例如:

<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;
}