查找实体集合中所有ID集合的最有效方法

时间:2014-05-22 16:55:55

标签: java collections guava apache-commons

我有一个实体:

public class Entity
{
    private long id;    
    private String data;

    public long getId() {
        return id;
    }

    public String getData() {
        return data;
    }
}

和一组实体:

Collection<Entity> entities= ...

查找Collection<Long>中所有ID的entities的最有效方法是什么?

6 个答案:

答案 0 :(得分:39)

假设你有

class Entity {
    final long id;
    final String data;

    public long getId() {
        return id;
    }

    public String getData() {
        return data;
    }

    Entity(long id, String data) {
        this.id = id;
        this.data = data;
    }
}

在Java 8中,您可以编写

Collection<Entity> entities = Arrays.asList(new Entity(1, "one"), 
                  new Entity(11, "eleven"), new Entity(100, "one hundred"));
// get a collection of all the ids.
List<Long> ids = entities.stream()
                         .map(Entity::getId).collect(Collectors.toList());

System.out.println(ids);

打印

[1, 10, 100]

你可以想象这在Java 7或更低版​​本中相当丑陋。注意Entity.getId应用于map()意味着在每个元素上调用此方法。

现在,真正有趣的部分是你可以做到这一点。

List<Long> ids = entities.parallelStream()
                         .map(Entity::getId).collect(Collectors.toList());

大多数情况下使用并行流会损害性能,但它会尝试它并且看起来非常简单(可能太容易了);


最有效的方法是拥有或构建地图。

Map<Long, Entity> entitiesMap = ...
// get all ids
Collection<Long> addIds = entitiesMap.keySet();

// look up entities by id.
List<Long> ids = ...
List<Entity> matching = new ArrayList<>();
for(Long id: ids)
    matching.add(entitiesMap.get(id));

答案 1 :(得分:2)

效率最高?基本上只是迭代并添加到列表中。你必须看看每个项目。

Collection<Long> ids = new LinkedList<Long>();
for (Entity e : entities) {
    ids.add(e.id);
}

或者,如果您可以使用Java 1.8,则可以执行以下操作:

entities.forEach((e) -> ids.add(e.id));

答案 2 :(得分:2)

你不会得到任何短于:

Collection<Long> ids = new ArrayList<>();
for (Entity e : entities) ids.add(e.getId());
  

我认为所有方法都会迭代集合

不一定。这将创建一个由底层实体集合直接支持的集合(实体集合的未来更改将显示在ids集合中):

Collection<Long> ids = new AbstractCollection<Long>() {
    @Override
    public int size() {
        return entities.size();
    }

    @Override
    public Iterator<Long> iterator() {
        return new Iterator<Long>() {
            private Iterator<Entity> base = entities.iterator();
            @Override public boolean hasNext() { return base.hasNext(); }
            @Override public Long next() { return base.next().getId(); }
            @Override public void remove() { base.remove(); }
        };
    }
};

答案 3 :(得分:1)

我不知道这是否一定是效率最高的,但对于Java 8之前的版本,我已经喜欢使用此处所述的属性界面:http://blog.cgdecker.com/2010/06/property-interfaces-and-guava.html

如博客文章所述,您将拥有一个名为HasId的简单界面:

public interface HasId {
    long getId();
}

您的实体类看起来像这样:

public class Entity implements HasId {
    private long id;    
    private String data;

    public long getId() {
        return id;
    }

    public String getData() {
        return data;
    }
}

你可以在某个地方找到一个简单的函数:

public class ToId implements Function<HasId, Long> {
    public Long apply(HasId hasId) {
        return hasId.getId();
    }
}

最后,要使用它:

Collection<Long> ids = Collections2.transform(entities, new ToId());

如果您只需要一件事情,那就太过分了,但是如果您有大量可以巧妙地实现HasId或其他类似接口的对象,我觉得使用起来非常愉快。

答案 4 :(得分:0)

而不是将列表转换为流,然后再返回列表

我会在下面推荐

集合ID =新的LinkedList(); Entity.forEach((e)-> ids.add(e.id));

答案 5 :(得分:0)

我们也可以尝试这种方法

List<Long> ids = new ArrayList<>();
entities.Stream().map(entity->ids.add(entity.getId()));
相关问题