如何匹配流中的equals()和hashCode?
How to match equals() and hashCode in streams?
我有一个流,我在其中聚合一些这样的数据:
//start comparator -> I take a string in format month-year (2-2022) and I want to order all the
//dates asc (day is not important here so I add by default first day from the month)
Comparator<String> c = (String s1, String s2)->{
String[] s1Data = s1.split("-");
String[] s2Data = s2.split("-");
LocalDate first = LocalDate.of(Integer.parseInt(s1Data[1]), Integer.parseInt(s1Data[0]),1);
LocalDate second = LocalDate.of(Integer.parseInt(s2Data[1]), Integer.parseInt(s2Data[0]),1);
System.out.println(second + " is after " + first);
if (first.isBefore(second))
return -1;
else
return 1;
};
//end comparator
//start stream
Map<String, Map<String, Map<EventType, Long>>> outputStream = timeSheetDTOS.stream().
collect(Collectors.groupingBy(
t -> t.getFirstName() + " " + t.getLastName(), TreeMap ::new,
Collectors.groupingBy(t -> t.getDayOfWork().get(ChronoField.MONTH_OF_YEAR) + "-" + t.getDayOfWork().get(ChronoField.YEAR), **()-> new TreeMap<>(c)**,
Collectors.groupingBy(TimeSheetDTO::getTaskType, TreeMap ::new , Collectors.counting())
)
));
问题是,通过添加这个比较器,我打破了 hashCode() 和 equals() 之间的契约,最后我有重复的钥匙:
有人知道我该如何解决这个问题吗?或者有没有办法在第二个映射的键之后对流返回的最终对象( Map>>)进行排序?
我的整个地图是这样的:
<"Some String",<"2-2022",<"HOLIDAY",2>>>
我想在“2-2022”之后按升序排序。
谢谢
你的比较器坏了。比较器有他们需要遵守的规则;其中之一是交换性;如果您的比较器声称 a
低于 b
,则 b
必须高于 a
。您的实施情况并非如此;如果 a 和 b 相等,您的比较器会说 'a' 高于 'b',并且 'b' 高于 'a'.
Return 0 表示相同的东西。最简单的方法是使用 java 的内置内容:
Comparator<String> c = Comparator.comparing((String s) -> {
String[] sData = s.split("-");
return LocalDate.of(Integer.parseInt(sData[1]), Integer.parseInt(sData[0]), 1);
});
更短,更容易阅读,而且..正确,这很好。
注意:equals 和 hashCode 在这里完全不相关。 TreeMap 不会以任何方式调用或使用它们;它对所有内容都使用比较器。问题是您损坏的比较器实现。
我有一个流,我在其中聚合一些这样的数据:
//start comparator -> I take a string in format month-year (2-2022) and I want to order all the
//dates asc (day is not important here so I add by default first day from the month)
Comparator<String> c = (String s1, String s2)->{
String[] s1Data = s1.split("-");
String[] s2Data = s2.split("-");
LocalDate first = LocalDate.of(Integer.parseInt(s1Data[1]), Integer.parseInt(s1Data[0]),1);
LocalDate second = LocalDate.of(Integer.parseInt(s2Data[1]), Integer.parseInt(s2Data[0]),1);
System.out.println(second + " is after " + first);
if (first.isBefore(second))
return -1;
else
return 1;
};
//end comparator
//start stream
Map<String, Map<String, Map<EventType, Long>>> outputStream = timeSheetDTOS.stream().
collect(Collectors.groupingBy(
t -> t.getFirstName() + " " + t.getLastName(), TreeMap ::new,
Collectors.groupingBy(t -> t.getDayOfWork().get(ChronoField.MONTH_OF_YEAR) + "-" + t.getDayOfWork().get(ChronoField.YEAR), **()-> new TreeMap<>(c)**,
Collectors.groupingBy(TimeSheetDTO::getTaskType, TreeMap ::new , Collectors.counting())
)
));
问题是,通过添加这个比较器,我打破了 hashCode() 和 equals() 之间的契约,最后我有重复的钥匙:
有人知道我该如何解决这个问题吗?或者有没有办法在第二个映射的键之后对流返回的最终对象( Map
我的整个地图是这样的:
<"Some String",<"2-2022",<"HOLIDAY",2>>>
我想在“2-2022”之后按升序排序。
谢谢
你的比较器坏了。比较器有他们需要遵守的规则;其中之一是交换性;如果您的比较器声称 a
低于 b
,则 b
必须高于 a
。您的实施情况并非如此;如果 a 和 b 相等,您的比较器会说 'a' 高于 'b',并且 'b' 高于 'a'.
Return 0 表示相同的东西。最简单的方法是使用 java 的内置内容:
Comparator<String> c = Comparator.comparing((String s) -> {
String[] sData = s.split("-");
return LocalDate.of(Integer.parseInt(sData[1]), Integer.parseInt(sData[0]), 1);
});
更短,更容易阅读,而且..正确,这很好。
注意:equals 和 hashCode 在这里完全不相关。 TreeMap 不会以任何方式调用或使用它们;它对所有内容都使用比较器。问题是您损坏的比较器实现。