简体   繁体   中英

Get data from a CSV file into a Custom Collector

I am trying to get Car data from a CSV file and collect that data into a Custom Collector which will return a List<Car> .

Car.csv

CAR_NAME,CAR_MODEL,CAR_PRICE,CAR_MILEAGE,CAR_DETAILS
Jeep,Cherokee,45000,14000,Petrol
Nissan,Juke,10000,20000,Diesel
BMW,1 Series,9600,29000,Petrol
Mercedes,A Class,15000,40000,Petrol
BMW,5 Series,15000,7500,Petrol
Mercedes,C 220,23000,2000,Petrol
Mercedes,GLE,65000,40000,Diesel
Land Rover,Discovery Sport,15000,46000,Diesel
BMW,4 Series,25000,66000,Diesel
Nissan,Qashqai,4000,200000,Diesel
Toyota,Yaris,7500,12000,Hybrid
Ford,Mondeo,6500,47000,Diesel
Mercedes,B Class,8700,80000,Diesel
Ford,Mustang,68000,84000,Petrol
Peugeot,307cc,4500,58000,Diesel
Nissan,Almera,2000,48000,Petrol
Peugeot,207cc,6000,32000,Petrol
Fiat,Punto,500,223000,Petrol
Seat,Ibiza,990,78000,Diesel
BMW,8 Series,54000,45000,Hybrid
Range Rover,Evoque,25000,34000,Diesel
Ford,Focus,34000,126000,Diesel

My Car POJO

import java.util.List;
import java.util.Objects;

public class Car {

    private String name;
    private String model;
    private String price;
    private String mileage;
    private List<String> carDetails;

    public Car(String name, String model, String price, String mileage) {
        super();
        this.name = name;
        this.model = model;
        this.price = price;
        this.mileage = mileage;
    }

    public Car(String name, String model, String price, String mileage, List<String> carDetails) {
        super();
        this.name = name;
        this.model = model;
        this.price = price;
        this.mileage = mileage;
        this.carDetails = carDetails;
    }

    public String getName() {
        return name;
    }

    public String getModel() {
        return model;
    }

    public String getPrice() {
        return price;
    }

    public String getMileage() {
        return mileage;
    }

    public List<String> getCarDetails() {
        return carDetails;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Car)) return false;
        Car car = (Car) o;
        return Objects.equals(name, car.name) &&
                Objects.equals(model, car.model) &&
                Objects.equals(price, car.price) &&
                Objects.equals(mileage, car.mileage) &&
                Objects.equals(carDetails, car.carDetails);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, model, price, mileage, carDetails);
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", model='" + model + '\'' +
                ", price='" + price + '\'' +
                ", mileage='" + mileage + '\'' +
                ", carDetails=" + carDetails +
                '}';
    }
}

My Main Class

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

public class StreamDeepDive {

    public static void main(String[] args) throws IOException {
        System.out.println(getData());
    }

    private static List<Car> getData() throws IOException {
        String filePath = "src/main/resources/cars.csv";
        List<Car> cars =  Files.lines(Paths.get(filePath)).skip(1).collect(toCarCollector()); // error is here
        return cars;
    }

    public static CarCollector toCarCollector(){
        return new CarCollector();
    }

    /**
     * My Custom Collector
     */
    private static class CarCollector implements Collector<Car, List<Car>, List<Car>> {

        @Override
        public Supplier<List<Car>> supplier() {
            return ArrayList::new;
        }

        @Override
        public BiConsumer<List<Car>, Car> accumulator() {
            return (List<Car> list, Car car) -> list.add(car);
        }

        @Override
        public BinaryOperator<List<Car>> combiner() {
            return (list1, list2) -> {
                list1.addAll(list2);
                return list1;
            };
        }

        @Override
        public Function<List<Car>, List<Car>> finisher() {
            return Function.identity();
        }

        @Override
        public Set<Characteristics> characteristics() {
            return null;
        }
    }
}

However, the error I am getting when I try to run this is: reason: no instance(s) of type variable(s) exist so that String conforms to Car . I have tried to look for resource online to try and see how I can convert a String into a custom Type ie Car within the BiConsumer but it is proving to be a challenge for me.

A few observations:

  1. You don't need a custom collector, using Collectors.toList() should work out-of-the-box.

  2. You are never creating your Car objects from each line. I would use a Stream.map operation for that, that either receives a whole line in its constructor (so I could use Car::new as the mapper function), or that receives each needed field, which I'd take after using String.split by a comma in each line.

  3. Also, you should use a try-with-resources construct so that the stream and the underlying InputStream are correctly closed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM