通过流比较集合中元素的所有组合 API
Comparing all combinations of elements in a Collection via the Streams API
我正在尝试比较 HashMap
中元素的所有组合(即没有重复比较)并返回满足所述 HashMap 的所有元素的列表
比较函数,使用Java 8 Streams-API.
即我想要这样的东西:
// pseudo code, this isnt hashmaps work but hopefully it gets the point across
for(int i=0; i<myHashMap.entrySet().length, i++)
for(int j=i+1, j<myHashMap.entrySet().length) {
if(myComparison(entrySet.get(i), entrySet.get(j)))
myList.add(new myClass[] {entrySet.get(i), entrySet.get(j)})
}
但使用流 API。我有一个几乎可以使用 .forEach
并简单地迭代流两次的版本,但是这有 运行 重复比较的问题,因此再次将这些重复项添加到列表中。我相当确定 reduce
运算符能够完成我的工作
需要,但我根本不熟悉 Streams API,无法弄清楚如何实现所需的结果。
您需要为地图的 n entries/keys 生成所有不同的 k 组合。 post 展示了如何实现这样的算法 java-combinations-algorithm. But since I think the task is not to come up with such an algorithm, I would suggest to use a librarry which does that task for you. One of such library is combinatoricslib3。如果您碰巧已经在使用 Apache Commons 或 Guava,它们也有实现组合。
使用 combinatoricslib3,您的代码可能如下所示:
import java.util.Map;
import org.paukov.combinatorics3.Generator;
public class TestJavaClass {
public static void main(String[] args) {
Map<String,Integer> myMap = Map.of("Foo", 1, "Bar", 2, "Baz", 3);
Generator.combination(myMap.keySet())
.simple(2)
.stream()
.forEach(System.out::println);
}
}
输出:
[Foo, Baz]
[Foo, Bar]
[Baz, Bar]
我已经使用上面的键集来展示一个简单的例子。但如果您需要这些条目,您可以将其更改为:
Generator.combination(myMap.entrySet())...
获取条目组合:
[Foo=1, Baz=3]
[Foo=1, Bar=2]
[Baz=3, Bar=2]
不确定您的 myComparison
方法的作用,但由于您将它用作 if 语句中的条件,我假设它 returns 是一个布尔值。如果是这样,您可以将其用作过滤器以进一步处理流。通过你的方法 myComparison
和你的自定义 class MyClass
的虚拟实现,像下面这样的东西应该给你一个起点:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.paukov.combinatorics3.Generator;
import lombok.AllArgsConstructor;
public class TestJavaClass {
public static void main(String[] args) {
Map<String, Integer> myMap = Map.of("Foo", 1, "Bar", 2, "Baz", 3);
List<MyClass> result =
Generator.combination(myMap.entrySet())
.simple(2)
.stream()
.filter(comb -> myComparison(comb.get(0), comb.get(1)))
.map(comb -> new MyClass(comb.get(0), comb.get(1)))
.collect(Collectors.toList());
}
static boolean myComparison(Map.Entry<String, Integer> first, Map.Entry<String, Integer> second) {
return first.getValue() + second.getValue() <= 4;
}
@AllArgsConstructor
static class MyClass {
Map.Entry<String, Integer> one;
Map.Entry<String, Integer> two;
}
}
我正在尝试比较 HashMap
中元素的所有组合(即没有重复比较)并返回满足所述 HashMap 的所有元素的列表
比较函数,使用Java 8 Streams-API.
即我想要这样的东西:
// pseudo code, this isnt hashmaps work but hopefully it gets the point across
for(int i=0; i<myHashMap.entrySet().length, i++)
for(int j=i+1, j<myHashMap.entrySet().length) {
if(myComparison(entrySet.get(i), entrySet.get(j)))
myList.add(new myClass[] {entrySet.get(i), entrySet.get(j)})
}
但使用流 API。我有一个几乎可以使用 .forEach
并简单地迭代流两次的版本,但是这有 运行 重复比较的问题,因此再次将这些重复项添加到列表中。我相当确定 reduce
运算符能够完成我的工作
需要,但我根本不熟悉 Streams API,无法弄清楚如何实现所需的结果。
您需要为地图的 n entries/keys 生成所有不同的 k 组合。 post 展示了如何实现这样的算法 java-combinations-algorithm. But since I think the task is not to come up with such an algorithm, I would suggest to use a librarry which does that task for you. One of such library is combinatoricslib3。如果您碰巧已经在使用 Apache Commons 或 Guava,它们也有实现组合。
使用 combinatoricslib3,您的代码可能如下所示:
import java.util.Map;
import org.paukov.combinatorics3.Generator;
public class TestJavaClass {
public static void main(String[] args) {
Map<String,Integer> myMap = Map.of("Foo", 1, "Bar", 2, "Baz", 3);
Generator.combination(myMap.keySet())
.simple(2)
.stream()
.forEach(System.out::println);
}
}
输出:
[Foo, Baz]
[Foo, Bar]
[Baz, Bar]
我已经使用上面的键集来展示一个简单的例子。但如果您需要这些条目,您可以将其更改为:
Generator.combination(myMap.entrySet())...
获取条目组合:
[Foo=1, Baz=3]
[Foo=1, Bar=2]
[Baz=3, Bar=2]
不确定您的 myComparison
方法的作用,但由于您将它用作 if 语句中的条件,我假设它 returns 是一个布尔值。如果是这样,您可以将其用作过滤器以进一步处理流。通过你的方法 myComparison
和你的自定义 class MyClass
的虚拟实现,像下面这样的东西应该给你一个起点:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.paukov.combinatorics3.Generator;
import lombok.AllArgsConstructor;
public class TestJavaClass {
public static void main(String[] args) {
Map<String, Integer> myMap = Map.of("Foo", 1, "Bar", 2, "Baz", 3);
List<MyClass> result =
Generator.combination(myMap.entrySet())
.simple(2)
.stream()
.filter(comb -> myComparison(comb.get(0), comb.get(1)))
.map(comb -> new MyClass(comb.get(0), comb.get(1)))
.collect(Collectors.toList());
}
static boolean myComparison(Map.Entry<String, Integer> first, Map.Entry<String, Integer> second) {
return first.getValue() + second.getValue() <= 4;
}
@AllArgsConstructor
static class MyClass {
Map.Entry<String, Integer> one;
Map.Entry<String, Integer> two;
}
}