使用流映射嵌套对象以配对列表中的所有可能组合
Mapping nested objects using streams to pair all possible combinations in a List
假设我有一个嵌套对象,其中包含一对不同的 String-Integer 对象(我们将每一对称为 endpoint
)。有一个名为 pair
的列表,它恰好包含 2 个 endpoint
对象。另一个名为 pairs
的列表可以包含任意数量的(比如 n
)pair
条目,我需要在新对象中收集每对唯一的字符串及其相应的整数值。
考虑以下 类 现有对象:
public class Endpoint {
private String key;
private Integer number;
public Endpoint(String key, Integer number) {
this.key = key;
this.number = number;
}
// Getters, Setters and toString()
}
public class Pair {
// It will have exactly 2 entries
List<Endpoint> pair;
public Pair(List<Endpoint> pair) {
this.pair = pair;
}
// Getters, Setters and toString()
}
考虑以下对象(转换前),其中 pairs
是一个 List<Pair>
。 pairs
中的条目可以按任何顺序排列:
pairs: [
pair: [{"p1",1000},{"p2",2000}],
pair: [{"p1",3000},{"p3",4000}],
pair: [{"p2",5000},{"p3",6000}],
pair: [{"p1",2000},{"p2",3000}],
pair: [{"p1",2001},{"p2",3001}],
pair: [{"p1",4000},{"p3",5000}],
pair: [{"p1",4001},{"p3",5001}],
pair: [{"p2",6000},{"p3",7000}],
pair: [{"p2",6001},{"p3",7001}]
]
考虑以下 类 来填充结果:
public class CustomEndpoint {
private String key;
// `numbers` can have any number of entries
private List<Integer> numbers;
public CustomEndpoint(String key, List<Integer> numbers) {
this.key = key;
this.numbers = numbers;
}
// Getters, Setters and toString()
}
public class CustomPair {
// It will have exactly 2 entries
List<CustomEndpoint> pair;
public CustomPair(List<CustomEndpoint> pair) {
this.pair = pair;
}
// Getters, Setters and toString()
}
我需要采集如下:
custom-pairs: [
custom-pair: {[{"p1", [1000,2000,2001]}, {"p2", [2000,3000,3001]}]},
custom-pair: {[{"p1", [3000,4000,4001]}, {"p3", [4000,5000,5001]}]},
custom-pair: {[{"p2", [5000,6000,6001]}, {"p3", [6000,7000,7001]}]}
]
其中 custom-pairs
是 List<CustomPair>
。 numbers
列表中条目的顺序必须保持与输入 pair
相同。例如,由于 p1 中的 1000
与 p2 中的 2000
配对,如果 1000
是 p1 的 numbers
列表中的第一个条目,那么 2000
也必须是第一个条目numbers
p2 列表中的条目,用于 p1 和 p2 配对在一起的组合。
如何在 Java 中使用 Streams 执行此操作?
在您对 classes 及其结构进行说明后,我更新了我的答案。
基本上,您可以通过包含的两个端点的键对列表 pairs
中的 Pair
元素进行分组。为了使代码更具可读性,我在你的 Pair
class (getPairKeys
) 中添加了一个方法,其中 returns 两个端点的键链接在一起,但你可以避免它如果您愿意,只需将密钥直接链接到流中即可。
按键对 Pair
元素进行分组后,您将得到一个 Map
,其中每个链式键映射到具有相同键的 n Pair
个实例。此时,您可以流式传输 Map
s 个条目,将每个条目映射到 CustomPair
,按第一个 CustomEndpoint
的第一个数字对它们进行排序,并最终收集实例。
为了使我的解决方案有效,我假设 equals
(以及 hashCode
)的实现存在于 Pair
和 Endpoint
中.另外,正如我之前所说,我在你的 Pair
class 中添加了一个 getPairKeys
方法来获得一个 String
映射每个 Pair
和一个 getFirstPairInitialNumber
方法在CustomPair
class之间建立排序CustomPair
。我刚才提到的所有代码都可以在下面的 link 中查阅。我宁愿不 post 在这里避免文字墙,只关注实际的解决方案。
List<CustomPair> listRes = pairs.stream()
.collect(Collectors.groupingBy(Pair::getPairKeys)) //Grouping the Pairs by the keys of the two EndPoints (key1:key2)
.entrySet().stream() //Streaming the entries of the map
.map(entry -> {
String key1 = null, key2 = null;
//Lists for the values of the CustomEndpoint
List<Integer> listValues1 = new ArrayList<>();
List<Integer> listValues2 = new ArrayList<>();
//Retrieving the keys and adding each pair's number to the respective lists
for (Pair p : entry.getValue()) {
key1 = p.getPair().get(0).getKey();
key2 = p.getPair().get(1).getKey();
listValues1.add(p.getPair().get(0).getNumber());
listValues2.add(p.getPair().get(1).getNumber());
}
//Returning the new CustomPair in place of the two grouped by Pair
return new CustomPair(new ArrayList<>(List.of(
new CustomEndpoint(key1, listValues1),
new CustomEndpoint(key2, listValues2))));
})
.sorted(Comparator.comparing(CustomPair::getFirstPairInitialNumber)) //Ordering the CustomPair by the beginning of their endpoint range
.collect(Collectors.toList()); //Collecting the CustomPair
这是更新后的 link 来测试代码
输出
假设我有一个嵌套对象,其中包含一对不同的 String-Integer 对象(我们将每一对称为 endpoint
)。有一个名为 pair
的列表,它恰好包含 2 个 endpoint
对象。另一个名为 pairs
的列表可以包含任意数量的(比如 n
)pair
条目,我需要在新对象中收集每对唯一的字符串及其相应的整数值。
考虑以下 类 现有对象:
public class Endpoint {
private String key;
private Integer number;
public Endpoint(String key, Integer number) {
this.key = key;
this.number = number;
}
// Getters, Setters and toString()
}
public class Pair {
// It will have exactly 2 entries
List<Endpoint> pair;
public Pair(List<Endpoint> pair) {
this.pair = pair;
}
// Getters, Setters and toString()
}
考虑以下对象(转换前),其中 pairs
是一个 List<Pair>
。 pairs
中的条目可以按任何顺序排列:
pairs: [
pair: [{"p1",1000},{"p2",2000}],
pair: [{"p1",3000},{"p3",4000}],
pair: [{"p2",5000},{"p3",6000}],
pair: [{"p1",2000},{"p2",3000}],
pair: [{"p1",2001},{"p2",3001}],
pair: [{"p1",4000},{"p3",5000}],
pair: [{"p1",4001},{"p3",5001}],
pair: [{"p2",6000},{"p3",7000}],
pair: [{"p2",6001},{"p3",7001}]
]
考虑以下 类 来填充结果:
public class CustomEndpoint {
private String key;
// `numbers` can have any number of entries
private List<Integer> numbers;
public CustomEndpoint(String key, List<Integer> numbers) {
this.key = key;
this.numbers = numbers;
}
// Getters, Setters and toString()
}
public class CustomPair {
// It will have exactly 2 entries
List<CustomEndpoint> pair;
public CustomPair(List<CustomEndpoint> pair) {
this.pair = pair;
}
// Getters, Setters and toString()
}
我需要采集如下:
custom-pairs: [
custom-pair: {[{"p1", [1000,2000,2001]}, {"p2", [2000,3000,3001]}]},
custom-pair: {[{"p1", [3000,4000,4001]}, {"p3", [4000,5000,5001]}]},
custom-pair: {[{"p2", [5000,6000,6001]}, {"p3", [6000,7000,7001]}]}
]
其中 custom-pairs
是 List<CustomPair>
。 numbers
列表中条目的顺序必须保持与输入 pair
相同。例如,由于 p1 中的 1000
与 p2 中的 2000
配对,如果 1000
是 p1 的 numbers
列表中的第一个条目,那么 2000
也必须是第一个条目numbers
p2 列表中的条目,用于 p1 和 p2 配对在一起的组合。
如何在 Java 中使用 Streams 执行此操作?
在您对 classes 及其结构进行说明后,我更新了我的答案。
基本上,您可以通过包含的两个端点的键对列表 pairs
中的 Pair
元素进行分组。为了使代码更具可读性,我在你的 Pair
class (getPairKeys
) 中添加了一个方法,其中 returns 两个端点的键链接在一起,但你可以避免它如果您愿意,只需将密钥直接链接到流中即可。
按键对 Pair
元素进行分组后,您将得到一个 Map
,其中每个链式键映射到具有相同键的 n Pair
个实例。此时,您可以流式传输 Map
s 个条目,将每个条目映射到 CustomPair
,按第一个 CustomEndpoint
的第一个数字对它们进行排序,并最终收集实例。
为了使我的解决方案有效,我假设 equals
(以及 hashCode
)的实现存在于 Pair
和 Endpoint
中.另外,正如我之前所说,我在你的 Pair
class 中添加了一个 getPairKeys
方法来获得一个 String
映射每个 Pair
和一个 getFirstPairInitialNumber
方法在CustomPair
class之间建立排序CustomPair
。我刚才提到的所有代码都可以在下面的 link 中查阅。我宁愿不 post 在这里避免文字墙,只关注实际的解决方案。
List<CustomPair> listRes = pairs.stream()
.collect(Collectors.groupingBy(Pair::getPairKeys)) //Grouping the Pairs by the keys of the two EndPoints (key1:key2)
.entrySet().stream() //Streaming the entries of the map
.map(entry -> {
String key1 = null, key2 = null;
//Lists for the values of the CustomEndpoint
List<Integer> listValues1 = new ArrayList<>();
List<Integer> listValues2 = new ArrayList<>();
//Retrieving the keys and adding each pair's number to the respective lists
for (Pair p : entry.getValue()) {
key1 = p.getPair().get(0).getKey();
key2 = p.getPair().get(1).getKey();
listValues1.add(p.getPair().get(0).getNumber());
listValues2.add(p.getPair().get(1).getNumber());
}
//Returning the new CustomPair in place of the two grouped by Pair
return new CustomPair(new ArrayList<>(List.of(
new CustomEndpoint(key1, listValues1),
new CustomEndpoint(key2, listValues2))));
})
.sorted(Comparator.comparing(CustomPair::getFirstPairInitialNumber)) //Ordering the CustomPair by the beginning of their endpoint range
.collect(Collectors.toList()); //Collecting the CustomPair
这是更新后的 link 来测试代码