Find only repeated String attributes in list with Java 8
up vote
7
down vote
favorite
I know below is the code to find out the occurrence of each String attributes in list , how can I filter this list with only duplicates item i.e having more than 1 occurrence. Sorry I am new to java 8 .
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
java java-8 java-stream
New contributor
add a comment |
up vote
7
down vote
favorite
I know below is the code to find out the occurrence of each String attributes in list , how can I filter this list with only duplicates item i.e having more than 1 occurrence. Sorry I am new to java 8 .
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
java java-8 java-stream
New contributor
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I know below is the code to find out the occurrence of each String attributes in list , how can I filter this list with only duplicates item i.e having more than 1 occurrence. Sorry I am new to java 8 .
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
java java-8 java-stream
New contributor
I know below is the code to find out the occurrence of each String attributes in list , how can I filter this list with only duplicates item i.e having more than 1 occurrence. Sorry I am new to java 8 .
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
java java-8 java-stream
java java-8 java-stream
New contributor
New contributor
edited 8 hours ago
Aomine
33.2k62756
33.2k62756
New contributor
asked 8 hours ago
Rishabh Chaturvedi
362
362
New contributor
New contributor
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago
add a comment |
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago
add a comment |
4 Answers
4
active
oldest
votes
up vote
5
down vote
create a stream from the entrySet
and filter
:
List<Map.Entry<String, Long>> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(Collectors.toList());
or if you want to maintain a map then:
Map<String, Long> result = stringList().stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
on another note, if you just want the individual numbers that have more than or equal to 2 occurrences then you can do:
List<String> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(x -> x.getValue() >= 2)
.map(Map.Entry::getKey)
.collect(toList());
another option being:
List<String> result =
list.stream()
.filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
.distinct()
.collect(toList());
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.
– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
|
show 1 more comment
up vote
5
down vote
If your List
is mutable, you can directly remove all elements except their second occurrence:
// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");
// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);
// example output
example.forEach(System.out::println);// prints bar baz
The solution above keeps only one copy for each string having multiple occurrences while removing all strings having no duplicates. If you want to keep all duplicates and just remove those string not having duplicates, there is no way around determining the duplicate status first.
// same example input as above
// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);
// example output
example.forEach(System.out::println);// prints bar baz bar bar baz
Here, the temporary map can be created with a Stream operation with the same logic:
Map<String,Boolean> temp = example.stream()
.collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
add a comment |
up vote
3
down vote
The other way would be like this. after groupBy then remove entry with value=1;
result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.
– nullpointer
7 hours ago
3
@nullpointer there is no difference betweenresult.values().removeIf(v -> == 1)
andresult.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.
– Holger
7 hours ago
add a comment |
up vote
2
down vote
A simpler way to find that out could be
List<String> recurringItems = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toList());
Since for items occurring more than once, lastIndex wouldn't be equal to the first index.
Alternatively, you can use Collectors.toSet()
to ensure the items are listed only once in case you are not interested in their order of recurrence.
Set<String> recurringItemsOnce = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toSet());
Or using Collections.frequency
as:
Set<String> recurringItems = list.stream()
.filter(item -> Collections.frequency(list, item) >= 2)
.collect(Collectors.toSet());
this would retrieve duplicate items, e.g. if our list wasArrays.asList("1","2","3","1","56","4","4")
then as a result you'd have[1, 1, 4, 4]
instead of[1, 4]
which of course you could solve by adding adistinct
call after thefilter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.
– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the itemsdistinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.
– nullpointer
8 hours ago
3
Simpler in source code, but horrible regarding performance. The OP's original approach usinggroupingBy
as starting point is much preferable.
– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
indexOf
andlastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case offrequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.
– Holger
7 hours ago
|
show 1 more comment
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
create a stream from the entrySet
and filter
:
List<Map.Entry<String, Long>> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(Collectors.toList());
or if you want to maintain a map then:
Map<String, Long> result = stringList().stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
on another note, if you just want the individual numbers that have more than or equal to 2 occurrences then you can do:
List<String> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(x -> x.getValue() >= 2)
.map(Map.Entry::getKey)
.collect(toList());
another option being:
List<String> result =
list.stream()
.filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
.distinct()
.collect(toList());
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.
– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
|
show 1 more comment
up vote
5
down vote
create a stream from the entrySet
and filter
:
List<Map.Entry<String, Long>> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(Collectors.toList());
or if you want to maintain a map then:
Map<String, Long> result = stringList().stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
on another note, if you just want the individual numbers that have more than or equal to 2 occurrences then you can do:
List<String> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(x -> x.getValue() >= 2)
.map(Map.Entry::getKey)
.collect(toList());
another option being:
List<String> result =
list.stream()
.filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
.distinct()
.collect(toList());
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.
– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
|
show 1 more comment
up vote
5
down vote
up vote
5
down vote
create a stream from the entrySet
and filter
:
List<Map.Entry<String, Long>> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(Collectors.toList());
or if you want to maintain a map then:
Map<String, Long> result = stringList().stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
on another note, if you just want the individual numbers that have more than or equal to 2 occurrences then you can do:
List<String> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(x -> x.getValue() >= 2)
.map(Map.Entry::getKey)
.collect(toList());
another option being:
List<String> result =
list.stream()
.filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
.distinct()
.collect(toList());
create a stream from the entrySet
and filter
:
List<Map.Entry<String, Long>> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(Collectors.toList());
or if you want to maintain a map then:
Map<String, Long> result = stringList().stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(s -> s.getValue() >= 2)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
on another note, if you just want the individual numbers that have more than or equal to 2 occurrences then you can do:
List<String> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()))
.entrySet()
.stream()
.filter(x -> x.getValue() >= 2)
.map(Map.Entry::getKey)
.collect(toList());
another option being:
List<String> result =
list.stream()
.filter(x -> list.stream().filter(x::equals).limit(2).count() == 2)
.distinct()
.collect(toList());
edited 8 hours ago
answered 8 hours ago
Aomine
33.2k62756
33.2k62756
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.
– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
|
show 1 more comment
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.
– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
I would personally prefer filtering out based on a logic over creating stream twice.
– nullpointer
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
@nullpointer mhmmm.. what do you mean?
– Aomine
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.– nullpointer
7 hours ago
list.stream() .filter(x -> list.stream().filter..
was pointing out this.– nullpointer
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
@nullpointer so what do you suggest to replace that with?
– Aomine
7 hours ago
1
1
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
Well, at least one such solution has been added to my answer. Just a choice to avoid using stream twice.
– nullpointer
7 hours ago
|
show 1 more comment
up vote
5
down vote
If your List
is mutable, you can directly remove all elements except their second occurrence:
// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");
// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);
// example output
example.forEach(System.out::println);// prints bar baz
The solution above keeps only one copy for each string having multiple occurrences while removing all strings having no duplicates. If you want to keep all duplicates and just remove those string not having duplicates, there is no way around determining the duplicate status first.
// same example input as above
// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);
// example output
example.forEach(System.out::println);// prints bar baz bar bar baz
Here, the temporary map can be created with a Stream operation with the same logic:
Map<String,Boolean> temp = example.stream()
.collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
add a comment |
up vote
5
down vote
If your List
is mutable, you can directly remove all elements except their second occurrence:
// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");
// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);
// example output
example.forEach(System.out::println);// prints bar baz
The solution above keeps only one copy for each string having multiple occurrences while removing all strings having no duplicates. If you want to keep all duplicates and just remove those string not having duplicates, there is no way around determining the duplicate status first.
// same example input as above
// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);
// example output
example.forEach(System.out::println);// prints bar baz bar bar baz
Here, the temporary map can be created with a Stream operation with the same logic:
Map<String,Boolean> temp = example.stream()
.collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
add a comment |
up vote
5
down vote
up vote
5
down vote
If your List
is mutable, you can directly remove all elements except their second occurrence:
// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");
// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);
// example output
example.forEach(System.out::println);// prints bar baz
The solution above keeps only one copy for each string having multiple occurrences while removing all strings having no duplicates. If you want to keep all duplicates and just remove those string not having duplicates, there is no way around determining the duplicate status first.
// same example input as above
// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);
// example output
example.forEach(System.out::println);// prints bar baz bar bar baz
Here, the temporary map can be created with a Stream operation with the same logic:
Map<String,Boolean> temp = example.stream()
.collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
If your List
is mutable, you can directly remove all elements except their second occurrence:
// example list
List<String> example = new ArrayList<>();
Collections.addAll(example, "foo", "bar", "baz", "bar", "bar", "baz");
// actual operation
Map<String,Integer> temp = new HashMap<>();
example.removeIf(s -> temp.merge(s, 1, Integer::sum)!=2);
// example output
example.forEach(System.out::println);// prints bar baz
The solution above keeps only one copy for each string having multiple occurrences while removing all strings having no duplicates. If you want to keep all duplicates and just remove those string not having duplicates, there is no way around determining the duplicate status first.
// same example input as above
// actual operation
Map<String,Boolean> temp = new HashMap<>();
example.forEach(s -> temp.merge(s, true, (a,b) -> false));
example.removeIf(temp::get);
// example output
example.forEach(System.out::println);// prints bar baz bar bar baz
Here, the temporary map can be created with a Stream operation with the same logic:
Map<String,Boolean> temp = example.stream()
.collect(Collectors.toMap(Function.identity(), s -> true, (a,b) -> false));
example.removeIf(temp::get);
answered 6 hours ago
Holger
159k23222424
159k23222424
add a comment |
add a comment |
up vote
3
down vote
The other way would be like this. after groupBy then remove entry with value=1;
result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.
– nullpointer
7 hours ago
3
@nullpointer there is no difference betweenresult.values().removeIf(v -> == 1)
andresult.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.
– Holger
7 hours ago
add a comment |
up vote
3
down vote
The other way would be like this. after groupBy then remove entry with value=1;
result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.
– nullpointer
7 hours ago
3
@nullpointer there is no difference betweenresult.values().removeIf(v -> == 1)
andresult.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.
– Holger
7 hours ago
add a comment |
up vote
3
down vote
up vote
3
down vote
The other way would be like this. after groupBy then remove entry with value=1;
result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
The other way would be like this. after groupBy then remove entry with value=1;
result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
result.values().removeIf(v->v.intValue() == 1);
answered 7 hours ago
Hadi J
9,40431539
9,40431539
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.
– nullpointer
7 hours ago
3
@nullpointer there is no difference betweenresult.values().removeIf(v -> == 1)
andresult.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.
– Holger
7 hours ago
add a comment |
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.
– nullpointer
7 hours ago
3
@nullpointer there is no difference betweenresult.values().removeIf(v -> == 1)
andresult.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.
– Holger
7 hours ago
1
1
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.– nullpointer
7 hours ago
result.entrySet().removeIf(v -> v.getValue() == 1); Set<String> res = result.keySet();
would be better I believe.. you can remove the entry instead of removing a value specifically from a list of values.– nullpointer
7 hours ago
3
3
@nullpointer there is no difference between
result.values().removeIf(v -> == 1)
and result.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.– Holger
7 hours ago
@nullpointer there is no difference between
result.values().removeIf(v -> == 1)
and result.entrySet().removeIf(v -> v.getValue() == 1)
, except that the latter is more verbose. Both variants iterate over the map and remove matching entries.– Holger
7 hours ago
add a comment |
up vote
2
down vote
A simpler way to find that out could be
List<String> recurringItems = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toList());
Since for items occurring more than once, lastIndex wouldn't be equal to the first index.
Alternatively, you can use Collectors.toSet()
to ensure the items are listed only once in case you are not interested in their order of recurrence.
Set<String> recurringItemsOnce = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toSet());
Or using Collections.frequency
as:
Set<String> recurringItems = list.stream()
.filter(item -> Collections.frequency(list, item) >= 2)
.collect(Collectors.toSet());
this would retrieve duplicate items, e.g. if our list wasArrays.asList("1","2","3","1","56","4","4")
then as a result you'd have[1, 1, 4, 4]
instead of[1, 4]
which of course you could solve by adding adistinct
call after thefilter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.
– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the itemsdistinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.
– nullpointer
8 hours ago
3
Simpler in source code, but horrible regarding performance. The OP's original approach usinggroupingBy
as starting point is much preferable.
– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
indexOf
andlastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case offrequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.
– Holger
7 hours ago
|
show 1 more comment
up vote
2
down vote
A simpler way to find that out could be
List<String> recurringItems = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toList());
Since for items occurring more than once, lastIndex wouldn't be equal to the first index.
Alternatively, you can use Collectors.toSet()
to ensure the items are listed only once in case you are not interested in their order of recurrence.
Set<String> recurringItemsOnce = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toSet());
Or using Collections.frequency
as:
Set<String> recurringItems = list.stream()
.filter(item -> Collections.frequency(list, item) >= 2)
.collect(Collectors.toSet());
this would retrieve duplicate items, e.g. if our list wasArrays.asList("1","2","3","1","56","4","4")
then as a result you'd have[1, 1, 4, 4]
instead of[1, 4]
which of course you could solve by adding adistinct
call after thefilter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.
– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the itemsdistinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.
– nullpointer
8 hours ago
3
Simpler in source code, but horrible regarding performance. The OP's original approach usinggroupingBy
as starting point is much preferable.
– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
indexOf
andlastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case offrequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.
– Holger
7 hours ago
|
show 1 more comment
up vote
2
down vote
up vote
2
down vote
A simpler way to find that out could be
List<String> recurringItems = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toList());
Since for items occurring more than once, lastIndex wouldn't be equal to the first index.
Alternatively, you can use Collectors.toSet()
to ensure the items are listed only once in case you are not interested in their order of recurrence.
Set<String> recurringItemsOnce = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toSet());
Or using Collections.frequency
as:
Set<String> recurringItems = list.stream()
.filter(item -> Collections.frequency(list, item) >= 2)
.collect(Collectors.toSet());
A simpler way to find that out could be
List<String> recurringItems = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toList());
Since for items occurring more than once, lastIndex wouldn't be equal to the first index.
Alternatively, you can use Collectors.toSet()
to ensure the items are listed only once in case you are not interested in their order of recurrence.
Set<String> recurringItemsOnce = list.stream()
.filter(item -> list.lastIndexOf(item) != list.indexOf(item))
.collect(Collectors.toSet());
Or using Collections.frequency
as:
Set<String> recurringItems = list.stream()
.filter(item -> Collections.frequency(list, item) >= 2)
.collect(Collectors.toSet());
edited 7 hours ago
answered 8 hours ago
nullpointer
36.5k1072143
36.5k1072143
this would retrieve duplicate items, e.g. if our list wasArrays.asList("1","2","3","1","56","4","4")
then as a result you'd have[1, 1, 4, 4]
instead of[1, 4]
which of course you could solve by adding adistinct
call after thefilter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.
– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the itemsdistinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.
– nullpointer
8 hours ago
3
Simpler in source code, but horrible regarding performance. The OP's original approach usinggroupingBy
as starting point is much preferable.
– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
indexOf
andlastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case offrequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.
– Holger
7 hours ago
|
show 1 more comment
this would retrieve duplicate items, e.g. if our list wasArrays.asList("1","2","3","1","56","4","4")
then as a result you'd have[1, 1, 4, 4]
instead of[1, 4]
which of course you could solve by adding adistinct
call after thefilter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.
– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the itemsdistinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.
– nullpointer
8 hours ago
3
Simpler in source code, but horrible regarding performance. The OP's original approach usinggroupingBy
as starting point is much preferable.
– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
indexOf
andlastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case offrequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.
– Holger
7 hours ago
this would retrieve duplicate items, e.g. if our list was
Arrays.asList("1","2","3","1","56","4","4")
then as a result you'd have [1, 1, 4, 4]
instead of [1, 4]
which of course you could solve by adding a distinct
call after the filter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.– Aomine
8 hours ago
this would retrieve duplicate items, e.g. if our list was
Arrays.asList("1","2","3","1","56","4","4")
then as a result you'd have [1, 1, 4, 4]
instead of [1, 4]
which of course you could solve by adding a distinct
call after the filter
. on another note, it would be sufficient to keep it as is if the OP wants to get the occurrence of a particular number in the list which requires some additional searching... so ultimately it might be better to proceed with OP's approach.– Aomine
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the items
distinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.– nullpointer
8 hours ago
@Aomine Indeed, if the eventual result is desired to just have the items
distinct
would help. Otherwise, if the sequence in which the duplicates occur matters, this can still be used. Added both for completeness.– nullpointer
8 hours ago
3
3
Simpler in source code, but horrible regarding performance. The OP's original approach using
groupingBy
as starting point is much preferable.– Holger
7 hours ago
Simpler in source code, but horrible regarding performance. The OP's original approach using
groupingBy
as starting point is much preferable.– Holger
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
@Holger Can you shed some details over the horrible regarding performance part. SInce I was considering that collecting to a Map using a stream and then performing operations would still be equal in performance.
– nullpointer
7 hours ago
4
4
indexOf
and lastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case of frequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.– Holger
7 hours ago
indexOf
and lastIndexOf
are linear searches. You can even predict, that for unique elements, all elements of the list will be traversed when searching once from the beginning and once from the end, and you are repeating this for every element, so the worst case of your operation will be n×n. In case of frequency
, which counts all occurrences, it will always be n×n. Whereas the filling of the map will always be n operations, even if hash operation are more costly and it bears allocations, but that's a fixed constant factor, not growing with the number of elements.– Holger
7 hours ago
|
show 1 more comment
Rishabh Chaturvedi is a new contributor. Be nice, and check out our Code of Conduct.
Rishabh Chaturvedi is a new contributor. Be nice, and check out our Code of Conduct.
Rishabh Chaturvedi is a new contributor. Be nice, and check out our Code of Conduct.
Rishabh Chaturvedi is a new contributor. Be nice, and check out our Code of Conduct.
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53584012%2ffind-only-repeated-string-attributes-in-list-with-java-8%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
I like this way: How to check if exists any duplicate in Java 8 Streams?
– Juan Sebastian Ocampo Ospina
8 hours ago