Finding duplicated objects by two properties
Considering that I have a list of Person objects like this :
Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}
Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?
java java-8
add a comment |
Considering that I have a list of Person objects like this :
Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}
Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?
java java-8
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
1
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
1
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25
add a comment |
Considering that I have a list of Person objects like this :
Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}
Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?
java java-8
Considering that I have a list of Person objects like this :
Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}
Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?
java java-8
java java-8
asked Nov 15 '18 at 7:17
kkotkkot
387
387
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
1
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
1
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25
add a comment |
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
1
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
1
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
1
1
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
1
1
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25
add a comment |
4 Answers
4
active
oldest
votes
By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation
List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
add a comment |
I need to find if they were any duplicates in fullName - occupation pair, which has to be unique
Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.
In that case you can use a stateful anyMatch:
Collection<Person> input = new ArrayList<>();
Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));
You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.
add a comment |
First implement equals and hashCode in your person class and then use.
List<Person> personList = new ArrayList<>();
Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
.collect(Collectors.toSet());
If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.
add a comment |
I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.
public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
Map<String, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));
return map.values().stream()
.filter(personList -> personList.size() > 1)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Client code:
List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);
1
Alternatively, you may combine thefilterandflatMapstep:.flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be aString. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).
– Holger
Nov 15 '18 at 10:29
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53314218%2ffinding-duplicated-objects-by-two-properties%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation
List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
add a comment |
By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation
List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
add a comment |
By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation
List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());
By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation
List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());
answered Nov 15 '18 at 8:02
DeadpoolDeadpool
6,5892629
6,5892629
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
add a comment |
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
this is duplication of my answer IMHO
– oleg.cherednik
Nov 15 '18 at 8:03
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
but i did not copy that, did it my self and posted at same time @oleg.cherednik
– Deadpool
Nov 15 '18 at 8:04
add a comment |
I need to find if they were any duplicates in fullName - occupation pair, which has to be unique
Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.
In that case you can use a stateful anyMatch:
Collection<Person> input = new ArrayList<>();
Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));
You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.
add a comment |
I need to find if they were any duplicates in fullName - occupation pair, which has to be unique
Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.
In that case you can use a stateful anyMatch:
Collection<Person> input = new ArrayList<>();
Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));
You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.
add a comment |
I need to find if they were any duplicates in fullName - occupation pair, which has to be unique
Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.
In that case you can use a stateful anyMatch:
Collection<Person> input = new ArrayList<>();
Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));
You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.
I need to find if they were any duplicates in fullName - occupation pair, which has to be unique
Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.
In that case you can use a stateful anyMatch:
Collection<Person> input = new ArrayList<>();
Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));
You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.
edited Nov 17 '18 at 12:21
answered Nov 15 '18 at 7:46
Jorn VerneeJorn Vernee
20.6k33861
20.6k33861
add a comment |
add a comment |
First implement equals and hashCode in your person class and then use.
List<Person> personList = new ArrayList<>();
Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
.collect(Collectors.toSet());
If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.
add a comment |
First implement equals and hashCode in your person class and then use.
List<Person> personList = new ArrayList<>();
Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
.collect(Collectors.toSet());
If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.
add a comment |
First implement equals and hashCode in your person class and then use.
List<Person> personList = new ArrayList<>();
Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
.collect(Collectors.toSet());
If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.
First implement equals and hashCode in your person class and then use.
List<Person> personList = new ArrayList<>();
Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
.collect(Collectors.toSet());
If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.
answered Nov 15 '18 at 7:22
Khalid ShahKhalid Shah
1,4071921
1,4071921
add a comment |
add a comment |
I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.
public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
Map<String, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));
return map.values().stream()
.filter(personList -> personList.size() > 1)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Client code:
List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);
1
Alternatively, you may combine thefilterandflatMapstep:.flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be aString. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).
– Holger
Nov 15 '18 at 10:29
add a comment |
I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.
public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
Map<String, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));
return map.values().stream()
.filter(personList -> personList.size() > 1)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Client code:
List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);
1
Alternatively, you may combine thefilterandflatMapstep:.flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be aString. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).
– Holger
Nov 15 '18 at 10:29
add a comment |
I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.
public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
Map<String, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));
return map.values().stream()
.filter(personList -> personList.size() > 1)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Client code:
List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);
I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.
public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
Map<String, List<Person>> map = persons.stream()
.collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));
return map.values().stream()
.filter(personList -> personList.size() > 1)
.flatMap(List::stream)
.collect(Collectors.toList());
}
Client code:
List<Person> persons = Collections.emptyList();
List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);
answered Nov 15 '18 at 8:01
oleg.cherednikoleg.cherednik
7,10021119
7,10021119
1
Alternatively, you may combine thefilterandflatMapstep:.flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be aString. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).
– Holger
Nov 15 '18 at 10:29
add a comment |
1
Alternatively, you may combine thefilterandflatMapstep:.flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be aString. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).
– Holger
Nov 15 '18 at 10:29
1
1
Alternatively, you may combine the
filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).– Holger
Nov 15 '18 at 10:29
Alternatively, you may combine the
filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).– Holger
Nov 15 '18 at 10:29
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53314218%2ffinding-duplicated-objects-by-two-properties%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
add equals and hashCode in person class?
– SMA
Nov 15 '18 at 7:19
1
Have you checked out Java 8 Distinct by property ?
– Jorn Vernee
Nov 15 '18 at 7:22
1
Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.
– kkot
Nov 15 '18 at 7:25