基于id返回列表的元素

时间:2014-07-24 10:43:01

标签: java guava

有没有人知道任何花哨的番石榴功能会为我做以下事情。

考虑我有一个对象列表。每个对象都有一个id。我有一个10个对象的列表,其中id为1到10.我想基于id获取特定对象。我通常做的是

private MyObject findMyObjectById(List<MyObject> items, Integer id) {
   for (MyObject item : items) {
      if (id.equals(item.getId())) {
          return item;
      }
    }
    return null;
}

这是冗长和重复的,因为我无法输入id(因为各种原因,getId不在我拥有的任何界面中)

有没有花哨的番石榴方法来做到这一点?

3 个答案:

答案 0 :(得分:1)

在此示例中,我使用FluentIterable's firstMatch

同样在大多数情况下,请避免返回null,而不是Optional

private final int id;

public MyObject(final int id) {
    this.id = id;
}

public int getId() {
    return this.id;
}

@Override
public String toString() {
    return "MyObject [id=" + this.id + "]";
}

public static Optional<MyObject> findFirstByFilter(final List<MyObject> myObjects, final Predicate<MyObject> filter) {

    return FluentIterable.from(myObjects)
            .firstMatch(filter);
}

public static Optional<MyObject> findFirstById(final List<MyObject> myObjects, final Integer id) {

    return findFirstByFilter(myObjects, new Predicate<MyObject>() {

        @Override
        public boolean apply(final MyObject myObject) {

            return myObject.getId() == id;
        }
    });
}

public static void main(final String... args) {
    final List<MyObject> myObjects = ImmutableList.of(new MyObject(1), new MyObject(2));

    final Optional<MyObject> found = findFirstById(myObjects, 2);

    //MyObject [id=2]
    System.out.println(found.orNull());

    final Optional<MyObject> notFound = findFirstById(myObjects, 5);

    //null
    System.out.println(notFound.orNull());
}

Java 8版本:

private final int id;

public MyObject(final int id) {
    this.id = id;
}

public int getId() {
    return this.id;
}

@Override
public String toString() {
    return "MyObject [id=" + this.id + "]";
}

public static void main(final String... args) {

    final List<MyObject> myObjects = ImmutableList.of(new MyObject(1), new MyObject(2));

    final Optional<MyObject> found = myObjects.stream()
        .filter(myObject -> myObject.getId() == 2)
        .findAny();

    // MyObject [id=2]
    System.out.println(found.orElse(null));

    final Optional<MyObject> notFound = myObjects.stream()
        .filter(myObject -> myObject.getId() == 5)
        .findAny();

    // null
    System.out.println(notFound.orElse(null));
}

答案 1 :(得分:1)

我知道你不能总是修改你的代码到套件,但这是我在这里看到的模式(我现在找不到它)。我们现在在我们的实体对象,DTO等上使用了很多。

创建此界面:

public interface HasLongId {
  public long getId();
}

现在在LongIds类中:

public static final Function<HasLongId, Long> GetIndex =
    new Function<HasLongId, Long>() {
        @Override
        public Long apply(HasLongId hasId) {
            return hasId.getId();
        }
    };
public static class NameMatcher implements Predicate<HasLongId> {
    private final long id;
    public NameMatcher(long id) {   
        this.id = id;   
    } 
    @Override public boolean apply(HasLongId hasId) { 
        return id == hasId.getId(); 
    }
}

你可以这样做:

public static final <V extends HasLongId> Iterator<Long> of(Iterator<V> items) {
    return Iterators.transform(items, GetIndex);
}
public static final <V extends HasLongId> String join(Iterable<V> items) {
    return Joiner.on(',').skipNulls().join(of(items));
}
public static final <V extends HasLongId> ImmutableMap<Long, V> mapOf(Iterable<V> items)     {
    return Maps.uniqueIndex(items, GetIndex);
}
public static final <V extends HasLongId> V find(Iterable<V> iterable, Long id) {
    return Iterables.find(iterable, new NameMatcher(id));
}
public static final <V extends HasLongId> boolean contains(V[] array, Long id) {
    return Iterators.contains(of(Iterators.forArray(array)), id);
}

等等。 我们也有这个界面:

public interface HasName  {
    String getName();
}

包含名为Names的类,其中包含我们的实用程序方法。 希望这有点帮助。

答案 2 :(得分:0)

要回答您的具体问题,Iterables有一个find方法,需要Predicate。我不确定它是多么“花哨”,你必须实现一个{id}比较的Predicate类。

我会回应@JoachimIsaksson,但这似乎真的会从Map<Integer,MyObject>中受益。