Senthilkumar Gopal Senthilkumar Gopal - 3 months ago 13
Java Question

Transforming/Filtering a list of custom objects to another using Guava collections

I am trying to convert this below logic to possibly use Guava collections and cannot figure out which one suits best - filter or transform. Even if multi step how to ensure that the list on which filtering happens builts on itself.

Map<Long, Detail> map = new HashMap<>();
for (Detail detail : detailList) {
if (map.containsKey(detail.getAppId())) {
Detail currentDetail = map.get(detail.getAppId());
if (detail.getCreatedOn().before(currentDetail.getCreatedOn())) {
continue;
}
}
map.put(detail.getAppId(), detail);
}
return new ArrayList<>(map.values());


Where Detail is just a class with Long appId and Date createdOn.

Is it even possible to convert this specific logic to a Guava based one.

Explanation of the code: From the list of Detail objects, find the ones which are the most recently created ones per appId. If an appId has more than one detail, then pick only the latest one.

Can use only Java 7

Answer

I don't think you can somehow rewrite this code using filter or transform methods from Guava, but you can certainly benefit from other Guava methods.

First of all, using Multimaps.index(Iterable<V> values, Function<? super V, K> keyFunction) method you can clearly show that you want to break detailList into number of collections by appId:

Multimap<Integer, Detail> detailsByAppId = Multimaps.index(detailList,
        new Function<Detail, Integer>() {
          @Override
          public Integer apply(Detail detail) {
            return detail.getAppId();
          }
        }
);

Then you can iterate through this collection of collections and find the latest detail in each of them:

List<Detail> latestDetails = new ArrayList<Detail>();
for (Collection<Detail> detailsPerAppId : detailsByAppId.asMap().values()) {
  Detail latestDetail = Collections.max(detailsPerAppId, new Comparator<Detail>() {
    @Override
    public int compare(Detail d1, Detail d2) {
      return d1.getCreatedOn().compareTo(d2.getCreatedOn());
    }
  });
  latestDetails.add(latestDetail);
}
return latestDetails;