Guforu
Guforu

Reputation: 4023

Cut the list in Java

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

Answers (1)

Tunaki
Tunaki

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

Related Questions