2016-07-17 42 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