web-dev-qa-db-ja.com

エンティティのコレクション内のすべてのIDのコレクションを見つける最も効率的な方法

私にはエンティティがあります:

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

    public long getId() {
        return id;
    }

    public String getData() {
        return data;
    }
}

およびエンティティのコレクション:

Collection<Entity> entities= ...

entitiesのすべてのIDのCollection<Long>を見つける最も効率的な方法は何ですか?

19
rapt

あなたが持っていると仮定

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以下ではかなりugいです。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));
39
Peter Lawrey

最も効率的ですか?基本的には、繰り返してリストに追加するだけです。各項目を確認する必要があります。

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
kmera

以下よりも短くなることはありません。

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

これが必ずしも最も効率的かどうかはわかりませんが、Java 8以前では、ここで説明するようにプロパティインターフェイスを使用するのが好きになりました。 http://blog.cgdecker.com/2010/06 /property-interfaces-and-guava.html

ブログの投稿で説明されているように、HasIdのような名前のシンプルなインターフェイスがあります。

public interface HasId {
    long getId();
}

Entityクラスは次のようになります。

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

1つだけに必要な場合はこれは過剰ですが、HasIdまたはその他のインターフェイスを正常に実装できるオブジェクトが大量にある場合は、一緒に作業するのがとても楽しいと思います。

1
Scott Strang

代わりにリストをストリームに変換してからリストに戻す

私は以下をお勧めします

コレクションID = new LinkedList(); entities.forEach((e)-> ids.add(e.id));