使用Google Guava过滤和转换集合

时间:2013-10-03 12:40:42

标签: java collections guava jodatime

想象一下以下对象

class Trip {
  String name;
  int numOfTravellers;
  DateMidnight from;
  DateMidnight too;
}

我在java中编写了一个手动递归过滤器和转换方法。但是,我认为使用Google Guava可以更有说服力地写出来。

有人可以帮助我并告诉我如何重写这些以使其更具可读性吗?

基本上这个方法的作用是找到相同的条目,并通过改变日期字段来组合相同的条目

List<Trip> combineEqual(List<Trip> list) {
        int n = list.size() - 1;
        for (int i = n; i >= 0; i--) {
            for (int j = n; j >= 0; j--) {
                if (i == j) {
                    continue;
                }
                if (shouldCombineEqual(list.get(i), list.get(j))) {
                    Trip combined = combine(list.get(i), list.get(j));
                    list.remove(i);
                    list.remove(j);
                    list.add(Math.min(i, j), combined);
                    return combineEqual(liste);
                }
            }
        }
        return list;
    }


private boolean shouldCombineEqual(Trip a, Trip b) {
    return shouldCombineWith(a, b) || shouldCombineWith(b, a);
}

private boolean shouldCombineWith(Trip a, Trip b) {
    return a.too() != null
            && a.too().plusDays(1).equals(b.from)
            && areEqual(a, b);
}

private boolean areEqual(Trip a, Trip b) {
    return equal(a.name,b.name) && equal(a.numOfTravellers, b.numOfTravellers);
}

private boolean equal(Object a, Object b) {
    return a == null && b == null || a != null && a.equals(b);
}

private Trip combineEqual(Trip a, Trip b) {
    Trip copy = copy(a); //Just a copy method
    if (a.from.isAfter(b.from)) {
        Trip tmp = a;
        a = b;
        b = tmp;
    } // a is now the one with the earliest too date
    copy.from = a.from;
    copy.too = b.too;
    return copy;
}

2 个答案:

答案 0 :(得分:2)

我不认为番石榴在这里可以提供很多帮助。如果没有它,你可以做很多改进:

创建TripKey {String name; int numOfTravellers;},定义equals,然后使用它而不是错误的areEqual。通过按键将行程拆分为列表 - ListMultimap<TripKey, Trip>可以提供帮助。

对于每个键,根据from对相应的列表进行排序。尝试将每次旅行与以下所有旅行结合起来。如果它合并,只重新启动内部循环。这应该比你的解决方案更清晰(也更快)......所以我就此止步。

答案 1 :(得分:2)

我只是使用HashSet。

首先在trip对象中定义equals和hashcode。将第一个列表添加到集合中。然后遍历第二个列表,检查匹配的行程是否已经在集合中。类似的东西:

    public static Set<Trip> combineEquals(List<Trip> 11, List<Trip> 12) {
    Set<Trip> trips = new HashSet<>(11);
    for ( Trip t: 12) {
        if ( trips.contains(t)) {
            // combine whats in the set with t
        } else {
            trips.add(t);
        }
    }

    return trips;