Search code examples
javareflectionjava-8java-stream

Convert a Java List<POJO> to Map<String, List<Object>>, where the key is a field name and value is a list of values by field


Convert in Java a List<POJO> to Map<String, List<Object>>, where the key is a field name and value is a list of values by the field.

class Train {
    public final String source;
    public final String destination;
    public final double cost;

    public Train(String source, String destination, double cost) {
        this.source = source;
        this.destination = destination;
        this.cost = cost;
    }
}

For example:

List<Train> trains = Arrays.asList(
    new Train("A", "B", 10.0),
    new Train("C", "D", 20.0),
    new Train("E", "F", 30.0)
);

It should be converted to:

Map<String, List<Object>> = ...  // {source=[A, C, E], destination=[B, D, F], cost=[10.0, 20.0, 30.0]}

Note: This isn't a duplicate of Java 8 List<V> into Map<K, V> since it doesn't tell exactly how to transform data, but only implies using Collectors.toMap.


Solution

  • class Main {
        public static void main(String[] args) {
            List<Train> trains = Arrays.asList(
                    new Train("A", "B", 10.0),
                    new Train("C", "D", 20.0),
                    new Train("E", "F", 30.0)
            );
            Map<String, List<?>> map = Arrays.stream(Train.class.getFields())
                    .collect(Collectors.toMap(Field::getName, f -> trains.stream()
                            .map(x -> {
                                try {
                                    return f.get(x);
                                } catch (IllegalAccessException e) {
                                    throw new IllegalStateException(e);
                                }
                            }).collect(Collectors.toList())));
            System.out.println(map.get("source"));          // [A, C, E]
            System.out.println(map.get("destination"));     // [B, D, F]
        }
    }