2016-07-17 83 views
0

我有一個抽象類'實體'和實現不同接口的對象(擴展'實體')。 我也有一個ArrayList包含所有這些不同的對象。多個列表或列表和getSublist()(Java)

現在,如果我需要訪問實現某個接口(使用它的方法)的所有實體,我用下面的方法(返回「實體」實現接口「IDirectFire」的過濾列表):

public ArrayList<IDirectFire> getDirectFireSublist() {//direct fire sublist 
    ArrayList<IDirectFire> sublist = new ArrayList(); 
    entities.stream().filter((it) -> (it instanceof IDirectFire)).forEach((it) -> { 
     sublist.add((IDirectFire) it); 
    }); 
    return sublist; 
} 

現在我的問題: 我應該進一步使用這種方法還是應該創建一個新的ArrayList,除了'實體'之外還存在,我需要每次'實體'更改時手動更新?

我需要更新'實體'很多,所以我不確定存儲多個子列表是否更有效,並在每次'實體'更改時更新它們,或者如果我應該繼續使用方法來過濾'實體',並且將方法應用於這些子列表。請記住,這些子列表也將用於其他方法的循環中。例如:

private void resetFirestatusIDF() {//reset firestatus (IDirectFire) 
    getDirectFireSublist().stream().forEach((it) -> { 
     it.dfHasFired(false); 
    });} 

這是否可行? 在此先感謝!

+1

一般來說,應儘量避免使用'instanceof',因爲它被認爲是「設計氣味」 – wakjah

回答

0

如果您只需要遍歷一部分項目,則創建一個新列表會很浪費。只需返回已過濾的流。

public Stream<IDirectFire> getDirectFire() { 
    return entities.stream().filter((it) -> (it instanceof IDirectFire)); 
} 

你也可以使用番石榴,並返回一個過濾Iterable代替:

public Iterable<IDirectFire> getDirectFire() { 
    return FluentIterable.from(entities).filter(IDirectFire.class); 
} 

然後,遍歷所有的項目elswhere:

private void resetFirestatusIDF() { 
    getDirectFire().forEach((it) -> it.dfHasFired(false)); 
} 
+0

謝謝,雖然我目前沒有使用番石榴。 請看看吧! – paxikek

+0

Guava中的'filter(Class )'方法對於你正在做的事情來說很整潔,但除了'Stream'方法同樣好。他們都有'forEach'方法,這意味着循環的例子對於兩者都是相同的。 – Sam

0

最好過濾它們。它會以可忽略不計的性能下降的代價創建更清晰易懂的代碼,除非你過濾了幾百個元素,否則應該忽略不計。

我注意到的第二件事是你流的代碼片段1.使用我建議你和另一種方法是:

> public ArrayList<IDirectFire> getDirectFireSublist() { 
>  return entities.stream().filter((it) -> (it instanceof IDirectFire)).collect(Collectors.toList()); 
> } 
+0

非常感謝!我不確定它會對性能產生多大的影響。 – paxikek

1

現在我的問題:我應該進一步用這種方法工作或者我應該創建一個新的ArrayList,除了'實體'之外還存在,並且每次'實體'更改時都需要手動更新?

出於某些原因,您是否希望重複'entites'數據?

1)你可以把它們只放在一個專用的列表中。在這種情況下,您不需要getDirectFireSublist()。

2)您可以在兩個列表之間共享它們而不重複它們。 在這種情況下,您必須更新已添加和已刪除的實體元素,因爲只有已修改的元素纔會更新。但實施起來相當直接。

+0

新列表不會重複,而是過濾後的「實體」作爲自己的列表,所以是的,我的意思是一個專用列表。謝謝! – paxikek

0

在評論wakjah提到instanceof是一點點的設計氣味。考慮到這一點,一種替代解決方案是使用Visitor模式。

public abstract class Entity { 
    public abstract void acceptVisitor(EntityVisitor visitor); 
    ... 
} 

public interface IDirectFire { 
    default acceptVisitor(EntityVisitor visitor) { 
     visitor.visit(this); 
    } 
    ... 
} 

public class ResetFireStatusVisitor implements EntityVisitor { 
    public void visit(IDirectFire directFireEntity) { 
     directFireEntity.dfHasFired(false); 
    } 
} 

然後,遍歷所有的項目:

entities.forEach(entity -> entity.acceptVisitor(new ResetFireStatusVisitor())); 

ResetFireStatusVisitor電話dfHasFired(false)上任何實現IDirectFire。在EntityVisitor中,您可以爲Entity的其他子類型指定默認的無操作實現。

我並不是建議你爲簡單的情況做這件事,但對於大型設計,這可能是對這個問題有用的答案。另一方面,它可能不會 - 這種模式也有它的設計氣味。

+0

請問爲什麼instanceof是設計的氣味?我絕對看到訪問者的用處,只是好奇而已。 instanceof更容易出錯嗎?非常感謝! – paxikek

+0

太大的主題領域要評論,但有很多討論。這裏是最熱門的搜索結果:http://stackoverflow.com/questions/20589590/why-not-use-instanceof-operator-in-oop-design – Sam

+0

是的,很抱歉,顯然是一個大問題,我會做一些搜索。感謝您的鏈接和您的幫助! – paxikek