2017-09-29 30 views
2

我有超類對象的ArrayList,並且寫了這個方法來返回它的一個子類的ArrayList。將一個類作爲參數傳遞給返回該方法的對象的ArrayList的方法

public static ArrayList<SubClass> getSubClass(ArrayList<SuperClass> superObjects){ 
    ArrayList<SubClass> objects = new ArrayList<>(); 
    for (SuperClass superObject : superObjects) { 
     if (superObject instanceof SubClass) { 
      objects.add((SubClass) superObject); 
     } 
    } 
    return objects; 
} 

現在我想調用一個類似的方法從超類對象的相同ArrayList中提取不同子類的對象。有沒有一種方法來推廣這個代碼,以獲得一個類作爲參數,並返回該子類的對象的ArrayList?

+1

你可以通過在類的子類型和使用,但我覺得你可能沒有正確使用泛型。如果你需要一個'SubClass'列表,然後創建一個並使用它。如果你只需要一個取決於'SuperClass'行爲的列表,那就用它來代替。 –

回答

3

如果您傳入課程,則可以執行此過濾器,然後致電Class.isInstance()。這叫做runtime type token。這是流的版本和List接口:

public <T> List<T> filterList(List<? super T> list, Class<T> subClass) { 
    return list.stream(). 
      filter(o -> subClass.isInstance(o)). 
      map(o -> (T) o). 
      collect(Collectors.toList()); 
} 

如果你真的想用一個ArrayList,那麼你需要手動篩選:

public <T> ArrayList<T> filterList(List<? super T> list, Class<T> subClass) { 
    ArrayList<T> result = new ArrayList<>(); 
    for (Object obj : list) { 
     if (subClass.isInstance(obj)) { 
      result.add((T) obj); 
     } 
    } 
    return result; 
} 

您可以測試它像這樣:

List<Number> nums = new ArrayList<>(); 
    nums.add(1); 
    nums.add(2); 
    nums.add(3L); 
    nums.add(4L); 
    nums.add(5.0F); 
    nums.add(6.0F); 
    nums.add(7.0); 
    nums.add(8.0); 

    List<Integer> ints = filterList(nums, Integer.class); 

    // prints [1, 2] 
    System.out.println(Arrays.toString(ints.toArray())); 

運行時類型令牌是一種常見的泛型慣用語。例如。 EnumMap使用它太:

private static enum Foo {One, Two, Three} 
Map<Foo, Integer> map = new EnumMap(Foo.class); 

更新

按照意見從@Valentin Ruano,這是一個簡潔,無警告的基於流的過濾器:

public <T> ArrayList<T> filterList(List<? super T> list, Class<T> subClass) { 
    return list.stream(). 
    return list.stream(). 
      filter(o -> subClass.isInstance(o)). 
      map(o -> subClass.cast(o)). // warning-free casting 
      collect(Collectors.toCollection(ArrayList::new)); // forcing an ArrayList collector 
} 
+2

如果他想返回一個ArrayList而不是任何List,那麼就不需要「手動過濾器」,你可以定義你自己的收集器。事實上''''Collectors.toList()'''實際上是返回ArrayList實例,所以你可以簡單地複製代碼。 –

+0

那麼,這只是從第一個解決方案中拋棄? (沒有雙關語意圖) 我寧願不依賴於這種無證行爲。 –

+0

不,我不是建議你必須投入盲目的ArrayList ... Collectors.toList()實現可能會在未來發生變化,這將不再是真實的。不過,您可以將當前的Collectors.toList()或其等價的調用複製到更通用的Collectors方法,而不需要將其上傳到List,因此將其保存爲ArrayList ...我的觀點是您**不** *爲了返回ArrayList,需要*放棄使用流,正如你所回答的那樣。 –

相關問題