Multimaps#filterKeys 方法允许您通过匹配您编码的任意Predicate 的键来过滤现有的Multimap。它的返回值是一个Multimap,它只包含满足过滤谓词的条目。
首先,让我们定义一个辅助方法,它可以创建一个Predicate 来检查日期是否在指定范围内。
private static Predicate<LocalDate> between(final LocalDate begin, final LocalDate end) {
return new Predicate<LocalDate>() {
@Override
public boolean apply(LocalDate date) {
return (date.compareTo(begin) >= 0 && date.compareTo(end) <= 0);
}
};
}
之后,您可以使用谓词过滤您想要的范围。
void testFilterPayments() {
Multimap<LocalDate, BigDecimal> payments = ArrayListMultimap.create();
payments.put(LocalDate.parse("2016-12-25"), new BigDecimal("1000"));
payments.put(LocalDate.parse("2017-01-15"), new BigDecimal("250"));
payments.put(LocalDate.parse("2017-01-15"), new BigDecimal("1250"));
payments.put(LocalDate.parse("2017-01-15"), new BigDecimal("2250"));
payments.put(LocalDate.parse("2017-01-25"), new BigDecimal("500"));
payments.put(LocalDate.parse("2017-03-20"), new BigDecimal("500"));
payments.put(LocalDate.parse("2017-04-15"), new BigDecimal("1000"));
payments.put(LocalDate.parse("2017-06-15"), new BigDecimal("1000"));
System.out.println(Multimaps.filterKeys(payments,
between(LocalDate.parse("2017-01-01"), LocalDate.parse("2017-04-01"))));
// Output:
// {2017-01-25=[500], 2017-03-20=[500], 2017-01-15=[250, 1250, 2250]}
System.out.println(Multimaps.filterKeys(payments,
between(LocalDate.parse("2017-01-01"), LocalDate.parse("2017-01-15"))));
// Output:
// {2017-01-15=[250, 1250, 2250]}
System.out.println(Multimaps.filterKeys(payments,
between(LocalDate.parse("2016-01-01"), LocalDate.parse("2017-12-31"))));
// Output:
// {2017-06-15=[1000], 2017-01-25=[500], 2017-03-20=[500], 2016-12-25=[1000], 2017-01-15=[250, 1250, 2250], 2017-04-15=[1000]}
System.out.println(Multimaps.filterKeys(payments,
between(LocalDate.parse("2001-01-01"), LocalDate.parse("2015-12-31"))));
// Output:
// {}
}
我已简化此示例以使用默认日期格式进行解析。您的原始示例似乎使用了自定义 formatter,但所有相同的技术都适用于通过谓词进行过滤。
我的谓词实现匹配begin 和end 的包含范围。如果您有稍微不同的要求(例如排他范围,这样end 不包含在结果中),那么您可以相应地调整apply 的实现。
请注意 JavaDocs 中针对filterKeys 方法返回的Multimap 实例的一些细节,例如:
返回的多图是未过滤的实时视图;一个变化会影响另一个。
...
生成的多图视图具有不支持 remove() 的迭代器...
...
返回的多映射不是线程安全的或可序列化的,即使未过滤是。
...
许多过滤后的 multimap 的方法,例如 size(),遍历底层 multimap 中的每个键/值映射,并确定哪些满足过滤器。当不需要实时取景时,复制过滤后的多图并使用副本可能会更快。
作为补充说明,between 谓词可以通过更改方法签名以使用接受各种Comparable 类型的泛型来变得更加灵活,而不仅仅是LocalDate。
private static <T extends Comparable<? super T>> Predicate<T> between(final T begin, final T end) {
return new Predicate<T>() {
@Override
public boolean apply(T value) {
return (value.compareTo(begin) >= 0 && value.compareTo(end) <= 0);
}
};
}