Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting objects from List<X> based on some other list property collection

I've a class -

public class Data implements Identifiable{
    private Integer id;

    public Integer getId(){
        return id;
    }
}

now I've two collections-

List<Data> data1 = // few hundred Objects

Set<Integer> dataIds = // few object ids

I would like to extract the List<Data> from data1 which has ids in dataIds

How should be my approach? I'va guava in my classpath so can go with guava's Functional approach if comparable in performance/efficiency .

like image 935
Premraj Avatar asked Apr 21 '11 15:04

Premraj


2 Answers

Unless all you want to do is iterate through the result once or you need a reusable live filtered view, you probably want a non-view list containing the matches. Creating a List or Set to store the result and then iterating through the data list and adding matches is a perfectly good approach and easy to understand!

List<Data> result = Lists.newArrayList();
for (Data data : data1) {
  if (dataIds.contains(data.getId()))
    result.add(data);
}

I see your Data class implements an Identifiable interface. Given that, you could create a Function<Identifiable, Integer> that gets the ID... Identifiables.getIdFunction() or something. This is nice because it'd likely be useful in various other places (I talk about that approach in a blog post here). With that in place, doing this with Guava would be fairly simple as well:

Predicate<Identifiable> predicate = Predicates.compose(
    Predicates.in(dataIds), Identifiables.getIdFunction());
List<Data> filtered = Lists.newArrayList(Iterables.filter(data1, predicate));

This is basically functionally equivalent to the first example, but seems like it'd be harder to understand. Since there isn't any clear benefit to doing this (unlike in a situation where you want to just use the live view), my recommendation would be to just go with the first.

like image 184
ColinD Avatar answered Oct 04 '22 02:10

ColinD


How about

Collections2.filter(
    data1,
    new Predicate<Data>() {
       public boolean apply(Data d) {
         return dataIds.contains(d.getId());
       }
    }
)

p.s. remember not to overcomplicate things, unless truly necessary.

like image 27
mindas Avatar answered Oct 04 '22 03:10

mindas