我对Java8集合流功能有一些肤浅的了解,所以我不确定是否有以下可能:我想 filter
基于整数比较的集合,并将该值重新用于Map。
具体来说,我有一个 Collection<String> strings
并想把它的每一个值Map到levenshtein距离的一个固定值 String x
如果levenshtein距离小于 levenshteinLimit
.
String x = "some string";
Collection<String> strings = new LinkedList<>(Arrays.asList("not some string",
"some other string"));
int levenshteinLimit = 10;
Map<Integer, String> stringsLevenshteinMap = strings.stream()
.filter(string -> LevenshteinDistance.getDefaultInstance().apply(x, string) < levenshteinLimit)
.collect(Collectors.toMap(string -> LevenshteinDistance.getDefaultInstance().apply(x, string), Function.identity()));
System.out.println(stringsLevenshteinMap);
工作得很好,表达了我所寻找的结果,但需要对距离进行冗余计算。到目前为止这还不是问题。一个没有流的解决方案也是可能的。我想学点新东西。
我假设先过滤然后Map更有效,因为对象的数量可能更小,这意味着更少的工作。
上面的代码使用ApacheCommons文本1.1。示例项目可以在https://github.com/krichter722/java-filter-and-map-without-redundancy.
4条答案
按热度按时间42fyovps1#
具有tuple中间对象的对象应该可以工作:
k4aesqcs2#
如果您想避免一个临时对象持有键和值,您需要一个自定义收集器,它可以追溯内置收集器的功能,但是可以直接合并过滤。顺便说一下,我不这么认为
Collectors.toMap
在这里是合适的,因为不能保证每个距离只有一根弦。因此,我用Collectors.groupingBy
作为模板:这基本上做了什么
Collectors.groupingBy
是,但将其用法限制为对int
仅处理Map到低于指定限制的数字的元素。也可以将其概括为使用Function
和一个Predicate
相反。这个可以像这样使用
但必须强调的是,不能保证这比创建一个包含这两个值的临时对象更好;这取决于许多环境因素。一般来说,创建临时对象并不昂贵。使用holder对象的方法要灵活得多,尤其是在以后要更改流操作时。
1cklez4t3#
首先,您可以通过避免创建无用的linkedlist来加快代码的速度。
现在,关于您的问题,如果您想继续使用流来实现这一点,那么解决方案是将每个字符串Map到包含字符串及其距离的对象,然后过滤这些对象,然后收集到一个Map:
ssm49v7z4#
在我脑子里,我觉得这应该管用:
但正如我所说:这是我的想法,所以我不能保证功能性或可编译性。但这个想法应该是显而易见的。我们不需要计算两次,而是Map到计算出的值,然后继续进行过滤和收集。