Java 对象向量和 Sort/Group 第三个值
Java Vector of Object and Sort/Group by third value
我有一个客户向量:
Vector<Customer> customers = Vector<Customer>();
客户看起来像:
public class Customer {
private String firstName;
private String lastName;
private Customer partner;
}
示例数据:
- 彼得;母鹿;格洛丽亚文
- John, Doe, null
- 格洛丽亚;文;彼得·多伊
- 强尼;标签;空
我想通过将合作伙伴分组在一起来对这个向量进行排序。所以结果应该是这样的:
- 彼得;母鹿;格洛丽亚文
- 格洛丽亚;文;彼得·多伊
- John, Doe, null
- 强尼;标签;空
有什么想法可以有效地做到这一点吗?
首先,我尝试通过覆盖比较方法来使用自定义排序函数(用于集合)来解决此问题。
问题是我只是在比较同一个字段时才这样做的。
在这种情况下,我基本上必须比较类似这样的东西“this.compareTo(getPartner().getPartner());”但我无法进入 运行.
第二次尝试显然是手动一遍又一遍地遍历向量并“手动”对其进行排序,我宁愿避免这种情况,因为我认为这是一个常见问题,并且有人已经提出了更好的解决方案.
谢谢!
注意:class Vector
已过时,可能会被 List
接口的其他实现替换,例如 ArrayList
.
在 nullsLast
比较器的帮助下,将没有合作伙伴的客户放在最后,可以应用更简单的排序。
假设我们有以下测试数据:
Customer a = new Customer("Peter", "Doe");
Customer x = new Customer("Gloria", "Ven", a);
Customer b = new Customer("Adam", "Swan");
Customer z = new Customer("Mary", "Blake", b);
Customer p = new Customer("John", "Doe");
Customer y = new Customer("Kyle", "Flint");
List<Customer> data = Arrays.asList(a, b, p, x, y, z);
// a Vector may be created similarly
// Vector<Customer> data = new Vector<>(Arrays.asList(a, b, p, x, y, z));
Collections.shuffle(data);
System.out.println(data);
然后自定义比较器 byLastAndFirst
和 byPartnerLastAndFirst
被实现并应用于 partner
领域,然后是自己的客户。
Comparator<Customer> byLastAndFirst = Comparator.comparing(Customer::getLastName)
.thenComparing(Customer::getFirstName);
Comparator<Customer> byPartnerLastAndFirst = Comparator
.comparing(Customer::getPartner, Comparator.nullsLast(byLastAndFirst))
.thenComparing(byLastAndFirst);
data.sort(byPartnerLastAndFirst);
System.out.println(data);
这提供了以下结果:
[`Adam Swan` & `Mary Blake`, `Gloria Ven` & `Peter Doe`, `Mary Blake` & `Adam Swan`, `Peter Doe` & `Gloria Ven`, `John Doe` & NULL, `Kyle Flint` & NULL]
但是,此解决方案中的合作伙伴并未组合在一起。
可以使用 Stream API 实现额外的分组,方法是将客户收集到排序映射中,其中键是客户和合作伙伴的排序列表,合作伙伴可能是 null
,并且然后使用 Stream::flatMap
将地图的键映射回客户列表并排除 null
合作伙伴:
Comparator<List<Customer>> sort = Comparator.comparing(list -> list.get(0), byPartnerLastAndFirst);
data.stream()
.collect(Collectors.groupingBy(
c -> Arrays.asList(c, c.getPartner())
.stream()
.sorted(Comparator.nullsLast(byLastAndFirst))
.collect(Collectors.toList()),
() -> new TreeMap<>(sort),
Collectors.toList()
))
.keySet().stream() // Stream<List<Customer>>
.flatMap(list -> list.stream().filter(Objects::nonNull))
.forEach(System.out::println);
输出(可能会改进为不显示 NULL 伙伴)
`Mary Blake` & `Adam Swan`
`Adam Swan` & `Mary Blake`
`Peter Doe` & `Gloria Ven`
`Gloria Ven` & `Peter Doe`
`John Doe` & NULL
`Kyle Flint` & NULL
我有一个客户向量:
Vector<Customer> customers = Vector<Customer>();
客户看起来像:
public class Customer {
private String firstName;
private String lastName;
private Customer partner;
}
示例数据:
- 彼得;母鹿;格洛丽亚文
- John, Doe, null
- 格洛丽亚;文;彼得·多伊
- 强尼;标签;空
我想通过将合作伙伴分组在一起来对这个向量进行排序。所以结果应该是这样的:
- 彼得;母鹿;格洛丽亚文
- 格洛丽亚;文;彼得·多伊
- John, Doe, null
- 强尼;标签;空
有什么想法可以有效地做到这一点吗?
首先,我尝试通过覆盖比较方法来使用自定义排序函数(用于集合)来解决此问题。 问题是我只是在比较同一个字段时才这样做的。 在这种情况下,我基本上必须比较类似这样的东西“this.compareTo(getPartner().getPartner());”但我无法进入 运行.
第二次尝试显然是手动一遍又一遍地遍历向量并“手动”对其进行排序,我宁愿避免这种情况,因为我认为这是一个常见问题,并且有人已经提出了更好的解决方案.
谢谢!
注意:class Vector
已过时,可能会被 List
接口的其他实现替换,例如 ArrayList
.
在 nullsLast
比较器的帮助下,将没有合作伙伴的客户放在最后,可以应用更简单的排序。
假设我们有以下测试数据:
Customer a = new Customer("Peter", "Doe");
Customer x = new Customer("Gloria", "Ven", a);
Customer b = new Customer("Adam", "Swan");
Customer z = new Customer("Mary", "Blake", b);
Customer p = new Customer("John", "Doe");
Customer y = new Customer("Kyle", "Flint");
List<Customer> data = Arrays.asList(a, b, p, x, y, z);
// a Vector may be created similarly
// Vector<Customer> data = new Vector<>(Arrays.asList(a, b, p, x, y, z));
Collections.shuffle(data);
System.out.println(data);
然后自定义比较器 byLastAndFirst
和 byPartnerLastAndFirst
被实现并应用于 partner
领域,然后是自己的客户。
Comparator<Customer> byLastAndFirst = Comparator.comparing(Customer::getLastName)
.thenComparing(Customer::getFirstName);
Comparator<Customer> byPartnerLastAndFirst = Comparator
.comparing(Customer::getPartner, Comparator.nullsLast(byLastAndFirst))
.thenComparing(byLastAndFirst);
data.sort(byPartnerLastAndFirst);
System.out.println(data);
这提供了以下结果:
[`Adam Swan` & `Mary Blake`, `Gloria Ven` & `Peter Doe`, `Mary Blake` & `Adam Swan`, `Peter Doe` & `Gloria Ven`, `John Doe` & NULL, `Kyle Flint` & NULL]
但是,此解决方案中的合作伙伴并未组合在一起。
可以使用 Stream API 实现额外的分组,方法是将客户收集到排序映射中,其中键是客户和合作伙伴的排序列表,合作伙伴可能是 null
,并且然后使用 Stream::flatMap
将地图的键映射回客户列表并排除 null
合作伙伴:
Comparator<List<Customer>> sort = Comparator.comparing(list -> list.get(0), byPartnerLastAndFirst);
data.stream()
.collect(Collectors.groupingBy(
c -> Arrays.asList(c, c.getPartner())
.stream()
.sorted(Comparator.nullsLast(byLastAndFirst))
.collect(Collectors.toList()),
() -> new TreeMap<>(sort),
Collectors.toList()
))
.keySet().stream() // Stream<List<Customer>>
.flatMap(list -> list.stream().filter(Objects::nonNull))
.forEach(System.out::println);
输出(可能会改进为不显示 NULL 伙伴)
`Mary Blake` & `Adam Swan`
`Adam Swan` & `Mary Blake`
`Peter Doe` & `Gloria Ven`
`Gloria Ven` & `Peter Doe`
`John Doe` & NULL
`Kyle Flint` & NULL