java.util.stream.stream.distinct()方法如何工作?我可以覆盖流对象的equals()方法吗?
我的用例是,我试图使用
stream
的方法从类code> Studale> Student> studentCoursagping 。
POJO详细信息如下:
public class StudentCourseMapping implements Serializable{
private String name;
private String dept;
private Integer roll;
private String course;
以下是等等方法:
@Override
public boolean equals(Object obj) {
StudentCourseMapping other = (StudentCourseMapping) obj;
if (roll == null) {
if (other.roll != null)
return false;
} else if (!roll.equals(other.roll))
return false;
return true;
}
以下是实现:
public class RemoveDuplicateUsingStream {
public static void main(String[] args) {
List<StudentCourseMapping> studentCourceList = JacksonJSONReaderObjectMapper.jsonReader();
studentCourceList.stream().distinct().forEach(System.out::println);
StudentCourseMapping s0 = studentCourceList.get(0);
StudentCourseMapping s1 = studentCourceList.get(1);
System.out.println(s0.equals(s1));
Set<Integer> st = new HashSet();
List<StudentCourseMapping>studentCourceList2 = studentCourceList.stream().filter(s -> st.add(s.getRoll()))
.collect(Collectors.toCollection(ArrayList::new));
System.out.println(studentCourceList2.size());
}
}
输出IS
StudentCourseMapping [name=Alu, dept=Physics, roll=12, course=Quantum Theory]
StudentCourseMapping [name=Alu, dept=Physics, roll=12, course=English]
StudentCourseMapping [name=Sam, dept=Commerce, roll=16, course=English]
StudentCourseMapping [name=Sam, dept=Commerce, roll=16, course=Accounts]
StudentCourseMapping [name=Joe, dept=Arts, roll=19, course=English]
StudentCourseMapping [name=Joe, dept=Arts, roll=19, course=Hindi]
true
3
JacksonjsonreaderObjectmapper.jsonreader()
是一种自定义方法,读取以下JSON。我能够通过使用过滤器并添加到hashset
来实现相同的目标,但是我真的很想知道我独特的实现是什么问题。
{
"studentCourseMapping": [
{
"name": "Alu",
"dept": "Physics",
"roll": 12,
"course": "Quantum Theory"
},
{
"name": "Alu",
"dept": "Physics",
"roll": 12,
"course": "English"
},
{
"name": "Sam",
"dept": "Commerce",
"roll": 16,
"course": "English"
},
{
"name": "Sam",
"dept": "Commerce",
"roll": 16,
"course": "Accounts"
},
{
"name": "Joe",
"dept": "Arts",
"roll": 19,
"course": "English"
},
{
"name": "Joe",
"dept": "Arts",
"roll": 19,
"course": "Hindi"
}
]
}
当我尝试直接测试Equals方法时,它正常工作并返回true,因为s0
和s1
都滚动为12。
StudentCourseMapping s0 = studentCourceList.get(0);
StudentCourseMapping s1 = studentCourceList.get(1);
System.out.println(s0.equals(s1));
但是,当我使用时,
所有对象都被打印了,并且在试图在Eclipse中调试时,我写的独特方法没有被调用,但是文档应该称呼它。我正在使用JDK 11:
流&lt; t&gt;独特()
返回由不同元素组成的流(根据
My use case is that I am trying to use the distinct
method of Stream
to remove students with the same roll number from a list of objects of class StudentCourseMapping
.
POJO details are below:
public class StudentCourseMapping implements Serializable{
private String name;
private String dept;
private Integer roll;
private String course;
Below is the equals method:
@Override
public boolean equals(Object obj) {
StudentCourseMapping other = (StudentCourseMapping) obj;
if (roll == null) {
if (other.roll != null)
return false;
} else if (!roll.equals(other.roll))
return false;
return true;
}
Below is the implementation:
public class RemoveDuplicateUsingStream {
public static void main(String[] args) {
List<StudentCourseMapping> studentCourceList = JacksonJSONReaderObjectMapper.jsonReader();
studentCourceList.stream().distinct().forEach(System.out::println);
StudentCourseMapping s0 = studentCourceList.get(0);
StudentCourseMapping s1 = studentCourceList.get(1);
System.out.println(s0.equals(s1));
Set<Integer> st = new HashSet();
List<StudentCourseMapping>studentCourceList2 = studentCourceList.stream().filter(s -> st.add(s.getRoll()))
.collect(Collectors.toCollection(ArrayList::new));
System.out.println(studentCourceList2.size());
}
}
And the output is
StudentCourseMapping [name=Alu, dept=Physics, roll=12, course=Quantum Theory]
StudentCourseMapping [name=Alu, dept=Physics, roll=12, course=English]
StudentCourseMapping [name=Sam, dept=Commerce, roll=16, course=English]
StudentCourseMapping [name=Sam, dept=Commerce, roll=16, course=Accounts]
StudentCourseMapping [name=Joe, dept=Arts, roll=19, course=English]
StudentCourseMapping [name=Joe, dept=Arts, roll=19, course=Hindi]
true
3
JacksonJSONReaderObjectMapper.jsonReader()
is a custom method which reads the below JSON. I am able to achieve the same by using filter and adding to HashSet
but I really want to know what is wrong with my distinct implementation.
{
"studentCourseMapping": [
{
"name": "Alu",
"dept": "Physics",
"roll": 12,
"course": "Quantum Theory"
},
{
"name": "Alu",
"dept": "Physics",
"roll": 12,
"course": "English"
},
{
"name": "Sam",
"dept": "Commerce",
"roll": 16,
"course": "English"
},
{
"name": "Sam",
"dept": "Commerce",
"roll": 16,
"course": "Accounts"
},
{
"name": "Joe",
"dept": "Arts",
"roll": 19,
"course": "English"
},
{
"name": "Joe",
"dept": "Arts",
"roll": 19,
"course": "Hindi"
}
]
}
When I try to test the equals method directly it was working properly and returning true since both the s0
and s1
has roll as 12.
StudentCourseMapping s0 = studentCourceList.get(0);
StudentCourseMapping s1 = studentCourceList.get(1);
System.out.println(s0.equals(s1));
But when I am using distinct
all the objects are getting printed and also while trying to debug in Eclipse the distinct method I wrote is not getting called, but the documentation says it should be called. I am using JDK 11:
Stream<T> distinct()
Returns a stream consisting of the distinct elements (according to
Object.equals(Object))
of this stream.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如@RealSkeATDIC和@Jesper在评论中已经说过的那样,在您的
studentscoursapping
类中,您还需要覆盖hashcode()
根据您的equals()
实现,以正确比较流中的元素并仅保留不同的元素。实际上,尽管没有
hashcode()
在distract()
文档:提到了
equals()
,其文档介绍了hashCode方法的一般合同,该合同在hashcode()
文档。引用equals()
文档:实际上,一旦
hashCode()
方法被正确覆盖,您的摘要就会产生所需的输出。您也可以在As @RealSkeptic and @Jesper have already said in the comments, in your
StudentCourseMapping
class you also need to override thehashCode()
method according to yourequals()
implementation, in order to properly compare the elements in the stream and keep only the distinct ones.In fact, although no
hashCode()
redefinition is mentioned in thedistinct()
documentation:It is mentioned though the use of
equals()
, whose documentation introduces the general contract for the hashcode method, which is amply covered in thehashCode()
documentation. Quoting theequals()
documentation:In fact, once the
hashCode()
method is properly overridden, your snippet produces the desired output. You can also test it at OneCompiler.从理论上讲,您现有的实施将起作用,因为不同的是非平等价值。但是
stream()
实现distion()
使用linkedHashset
(它可以直接使用对象的hashcode 方法)捕获重复项。由于每个类引用都是唯一的,并且
hashCode
的默认实现基于该引用的值,因此不会从equals
perspective中获得重复。这是使用默认
HashCode
的简单演示。创建了10个对象的列表。然后,该列表反复添加到自身并改组中,从而列出了10,240个对象的列表,共有10个不同的哈希码。因此,当DISTICT()
方法检查这些Hashcodes
时,它将找到重复项并忽略它们。注意:此类使用简单且不完整的
等于
方法,该方法足以容纳该受控演示。打印类似的东西
In theory your existing implementation would work since distinct implies non equal values. But the
Stream()
implementation ofdistinct()
makes use of aLinkedHashSet
(which makes direct use of the object'shashCode
method) to catch the duplicates. Since each class reference is unique and the default implementation ofhashCode
is based on the value of that reference, duplicates from anequals
perspective will not be caught.Here is a simple demo using the default
hashCode
. A list of 10 objects is created. Then that list is repeatedly added to itself and shuffled resulting in a list of 10,240 objects, with a total of 10 distinct hashCodes. So when thedistinct()
method checks thosehashcodes
, it will find duplicates and ignore them.Note: This class uses a simple and incomplete
equals
method that is sufficient for this controlled demo.prints something like