将CSV文件中的数据导入自定义收集器

时间:2018-03-02 18:40:13

标签: java collections java-8 java-stream

我正在尝试从CSV文件中获取Car数据并将该数据收集到自定义收集器中,该收集器将返回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

我的车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 +
                '}';
    }
}

我的主要课程

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;
        }
    }
}

但是,当我尝试运行它时,我得到的错误是: reason: no instance(s) of type variable(s) exist so that String conforms to Car。我试图在线查找资源,试着看看我如何将String转换为Car中的自定义类型BiConsumer,但事实证明这对我来说是一个挑战。

1 个答案:

答案 0 :(得分:3)

一些观察结果:

  1. 您不需要自定义收藏家,使用Collectors.toList()即可开箱即用。

  2. 您永远不会从每一行创建Car个对象。我会使用Stream.map操作,在其构造函数中接收整行(因此我可以使用Car::new作为映射器函数),或者接收每个所需的字段,我可以d在每行使用逗号String.split之后。

  3. 此外,您应该使用try-with-resources构造,以便正确关闭流和基础InputStream