javalistjava-streammapping

(Java) How to map one column of a CSV file to another column of a different type?


So for this problem, my function is supposed to return the top-10 list of avengers with the most appearances (in decreasing order).
In the Avenger class it is much like a basic Person class however there are no getter functions, just fields that represent their name, gender, appearances, etc.

public class Avenger {
    public final String name;
    public final int appearances;
    public final String gender;
    public final int year;
    public final String honorary;
    public final String[] deaths;
    public final String[] returns;
    public final String notes;

    public Avenger(String name,
                   int appearances,
                   String gender,
                   int year,
                   String honorary,
                   String[] deaths,
                   String[] returns,
                   String notes) {
        this.name = name;
        this.appearances = appearances;
        this.gender = gender;
        this.year = year;
        this.honorary = honorary;
        this.deaths = deaths;
        this.returns = returns;
        this.notes = notes;
    }

    public static Avenger valueOf(String line) {
        String[] array = line.split(",");
        String name = array[0];
        int appearances = Integer.valueOf(array[1]);
        String gender = array[2];
        int year = Integer.valueOf(array[3]);
        String honorary = array[4];
        String[] deaths = new String[5];
        String[] returns = new String[5];
        String notes = array[15];

        int index = 5;
        int i = 0;
        while (index < 15) {
            deaths[i] = array[index++];
            returns[i] = array[index++];
            i++;
        }
        return new Avenger(name, appearances, gender, year, honorary, deaths, returns, notes);
    }

    @Override
    public String toString() {
        return "Avenger [name=" + name + ", appearances=" + appearances + ", gender=" + gender + ", year=" + year
                + ", honorary=" + honorary + ", deaths=" + Arrays.toString(deaths) + ", returns="
                + Arrays.toString(returns) + ", notes=" + notes + "]";
    }
}

My function is getting the top 10 APPEARANCES, and the numbers it is returning are correct.

static Function<Stream<Avenger>, List<String>> getTop10ByAppearances = a -> 
a.map(s -> s.appearances).sorted((x, y) -> y - x).limit(10)
.map(p -> p.toString()).collect(Collectors.toList());

However, I don't need it to return the numbers, I need it to return the NAMES that correspond to those numbers. So my question is How can I map what I have here to the names and then return the List<String> of those names?


Solution

  • To first order by appearance and then collect the name, you need to remove the first map operation, and perform a descending comparison by appearances:

    sorted(Comparator.comparingInt((Avenger x) -> x.appearances).reversed())

    Then, you could limit to the top 10 results, map each avenger to their name, and finally collect the results.

    static Function<Stream<Avenger>, List<String>> getTop10ByAppearances = a ->
                    a.sorted(Comparator.comparingInt((Avenger x) -> x.appearances).reversed())
                    .limit(10)
                    .map(p -> p.name)
                    .collect(Collectors.toList());