问题
I keep running into solutions where I want/think i need to save state via either a Map or a Set. e.g. create a method that returns duplicates found in the input
// non streams solution
public int[] getDuplicates(int[] input){
Set<Integer> allSet = new HashSet<Integer>();
Set<Integer> duplicates = new HashSet<Integer>();
int[] dups = new int[input.length];
int j = 0;
for (Integer i : input) {
if (!allSet.add(i)) {
if(duplicates.add(i)) {
dups[j++] = i;
}
}
}
return Arrays.copyOfRange(dups, 0, j);
}
My Java 8 Streams solution, unfortunately I am using a HashSet for filtering. I understand this is not "proper" as it depends on state. Is no state a suggestion or a hard-fast rule? Is it only an issue when running a parallel stream? Can someone suggest a way not to use HashSet here?
public static int[] getDuplicatesStreamsToArray(int[] input) {
Set<Integer> allSet = new HashSet<>();
int[] dups = Arrays.stream(input)
.sequential() // prevents parallel processing
.unordered() // speed up distinct operation
.boxed() // int to Integer
.filter(n -> !allSet.add(n)) // passes dups, but uses STATE
.distinct() // uses internal Set of dups
.mapToInt(i -> i) // Integer back to int
.toArray();
return dups;
}
回答1:
How about this:
Basically, creates a frequency count of type Map<Integer,Long>
and returns those keys
where the value
is greater than 1.
public static int[] getDuplicatesStreamsToArray(int[] input) {
int[] dups = Arrays.stream(input).boxed().collect(
Collectors.groupingBy(Function.identity(),
Collectors.counting())).entrySet().stream().filter(
e -> e.getValue() > 1).mapToInt(
e -> e.getKey()).toArray();
return dups;
}
I misunderstood what you were trying to do earlier.
来源:https://stackoverflow.com/questions/57083672/java-8-streams-how-to-avoid-filtering-with-map-or-set