Reputation: 4023
I created a class Data
in Java. This is a source code of this simple help class:
class Data {
private Integer x;
private Integer y;
Data(Integer x, Integer y) {
this.x = x;
this.y = y;
}
protected Integer get_x() {
return x;
}
protected Integer get_y() {
return y;
}
}
After that I use my class Data
to create some List<Data> container
. I add the elements in my container
with the help of the add
methods and sort my List. Finally I print out the output:
for(Data data : container){
System.out.println("Print x: " + data.get_x() + ", Print y: " + data.get_y());
}
The possible output could be:
Print x: 1, Print y: 3
Print x: 1, Print y: 5
Print x: 1, Print y: 2
Print x: 1, Print y: 4
Print x: 1, Print y: 5
Print x: 1, Print y: 2
Print x: 1, Print y: 6
Print x: 1, Print y: 7
Print x: 2, Print y: 3
Print x: 2, Print y: 5
Print x: 2, Print y: 2
Print x: 2, Print y: 4
Print x: 2, Print y: 5
Print x: 2, Print y: 2
Print x: 2, Print y: 6
Print x: 2, Print y: 7
...
The length of every unique x
-part could be variable, also I don't need to know, how many different values of x
I have in my List. Now my question is: is it possible to create another List (or modify this one), which have only limited and fixed number of top x
values in the list and remove the other? For example I want only 3 values for every x value. The output should be like:
Print x: 1, Print y: 3
Print x: 1, Print y: 5
Print x: 1, Print y: 2
Print x: 2, Print y: 3
Print x: 2, Print y: 5
Print x: 2, Print y: 2
Upvotes: 3
Views: 815
Reputation: 137174
A solution is to store a List<Data>
for each x
value you have in a Map<Integer, List<Data>>
.
Map<Integer, List<Data>> map = new HashMap<>();
for (Data data : container) {
List<Data> value = map.get(data.get_x());
if (value == null) {
map.put(data.get_x(), new ArrayList<>(Arrays.asList(data)));
} else if (value.size() < 3) {
value.add(data);
}
}
In this code, we loop over all the data and retrieve the current list for the current x
data. If it is null, it means there is currently no value so we add a new list containing only the current data (wrapping Arrays.asList
into a new ArrayList
because it returns a fixed-size list). Else, and if the list has less than 3 elements then we add the current one.
This will keep only the first 3 elements for each x
value.
Using Java 8, this loop can be simplified a little:
Map<Integer, List<Data>> map = new HashMap<>();
for (Data data : container) {
List<Data> list = map.computeIfAbsent(data.get_x(), k -> new ArrayList<Data>());
if (list.size() < 3) {
list.add(data);
}
}
If you want to have a List
of all the values (instead of a Map
), there is a simpler way (using Java 8): keep a Map<Integer, Integer>
mapping each x
value with the number of times it appears:
Map<Integer, Integer> map = new HashMap<>();
List<Data> filtered = new ArrayList<>();
for (Data data : container) {
int count = map.merge(data.get_x(), 1, Integer::sum);
if (count < 3) {
filtered.add(data);
}
}
The filtered
list will have the wanted results. In this code map.merge
inserts 1 if there was no mapping or else add 1 to the previous mapping.
Upvotes: 5