【问题标题】:How to convert List<String[]> into List<MyObject>?如何将 List<String[]> 转换为 List<MyObject>?
【发布时间】:2016-06-30 14:28:39
【问题描述】:

我有一个来自 csv 文件的列表。这个 csv 文件是这样填充的:

_Name_ |_Surname_|_Sex_
_nam1_ | _sur1_  | _s1_
_nam2_ | _sur2_  | _s2_

所以我这样做:

CSVReader reader = new CSVReader(new FileReader("file.csv"));
List<String[]> myEntries = reader.readAll();

现在,我想创建另一个 MyObject 类型的列表,例如:

List<MyObject> list = new ArrayList<MyObject>();

MyObject 类包含在哪里:

private String name;
private String surname;
private String sex;

用他们的get和set。 第一个列表中的内容应移至:

list.setName();
list.setSurname();
list.setSex();

我该怎么做?

【问题讨论】:

    标签: java string csv object


    【解决方案1】:

    您可以尝试以下方法:

    List<MyObject> list = new ArrayList<MyObject>();
    
    for(String[] entry : myEntries){
        MyObject obj = new MyObject();
        //assign values to properties of our object
        obj.setName(entry[0]);
        obj.setSurname(entry[1]);
        obj.setSex(entry[2]);
    
        //add object to list
        list.add(obj);
    }
    

    希望对你有帮助

    【讨论】:

    • 我认为您需要跳过第一行,因为它包含元信息。
    【解决方案2】:

    如果 MyObject.class 有一个可以处理您的 3 个信息的构造函数,那么您可以使用:

    for (String[] item : myEntries) {
            list.add(new MyObject(item[0], item[1], item[2]);
        }
    

    否则试试这个:

    for (String[] item : myEntries) {
            MyObject myObj = new MyObject();
            myObj.setName(item[0]);
            myObj.setSurname(item[1]);
            myObj.setSex(item[2]);
            list.add(myObj);
        }
    

    【讨论】:

    • 如果我的数组列表包含 1000 个字符串怎么办?
    • @Marco 我不明白你的意思?您的 ArrayList 只能包含 MyObject 类中的对象。
    • 表示 1000 列。姓名、姓氏、年龄、性别、身高、体重、国家、生日……
    • @Marco 你必须自己调用每个 Setter,或者你可以在 MyObject.class 中创建一个构造函数,它接受你可以传递你的 String 数组。
    • 我认为您需要跳过第一行,因为它包含元信息。
    【解决方案3】:

    如果您在对象类中创建匹配的构造函数(或转换器或其他),则可以使用流操作。

    public class MyObject {
        private String name;
        private String surname;
        private String sex;
    
        public MyObject(){}
    
        public static MyObject fromStringArr(String[] csvVals) {
            assert csvVals != null && csvVals.length >= 3;   
    
            MyObject m = new MyObject();
            m.name = csvVals[0];
            m.surname = csvVals[1];
            m.sex = csvVals[2];
            return m;
        }
    
        //Getters and setters for MyObject...
        //....
    }
    

    然后你可以直接读入你的对象类型。

    CSVReader reader = new CSVReader(new FileReader("file.csv"));
    List<MyObject> myEntries = reader.readAll().stream().skip(1).map(MyObject::fromStringArr).collect(Collectors.toList());
    

    【讨论】:

    • 我认为您需要跳过第一行,因为它包含元信息。
    【解决方案4】:

    假设MyObject有一个构造函数如:

    public final class MyObject {
    
        private final String name, surname, sex;
    
        public MyObject(final String name, final String surname, final String sex) {
            this.name = name;
            this.surname = surname;
            this.sex = sex;
        }
    }
    

    那么你可以这样做:

    List<MyObject> myObjects = reader.readAll()
                                     .stream()
                                     .map(entry -> new MyObject(entry[0], entry[1], entry[2]))
                                     .collect(Collectors.toList());
    

    使用拆分器的替代方法:

    List<MyObject> myObjects = StreamSupport.stream(csvReader::spliterator, ORDERED, true)
                                   .map(entry -> new MyObject(entry[0], entry[1], entry[2]))
                                   .collect(Collectors.toList());
    

    【讨论】:

    • 我认为您需要跳过第一行,因为它包含元信息。
    • @gevorg 我相信当您构造CSVReader 时有一个选项可以指定要跳过的行数
    • 是的,你是对的CSVReader line 参数就是为了这个:)
    【解决方案5】:

    第 1 步 - 确保正确初始化 CSVReader

    根据API documentationCSVReader(Reader reader, char separator, char quotechar, int line) 可以使用正确的构造函数跳过第一行,还需要指定quotecharseparator 以便它知道数据的格式。

    CSVReader reader = new CSVReader(new FileReader("file.csv"), ',', '_', 1);
    

    第 2 步 - 使用 java.util.stream 收集对象

    myEntries.forEach(entity -> {
        MyObject object = new MyObject();
    
        object.setName(entity[0]);
        object.setSurname(entity[1]);
        object.setSex(entity[2]);
    
        list.add(object);
    });
    

    或者更好地为它定义适当的构造函数,如下所示:

    public MyObject(String name, String surname, String sex) {
        setName(name);
        setSurname(surname);
        setSex(sex);
    }
    

    并简化循环:

    myEntries.forEach(entity -> list.add(new MyObject(entity[0], entity[1], entity[2]));
    

    问题 - 如果您有 1000 列怎么办?

    正如arizzle 提到的,在一个类中有1000 个字段并不是一个好主意,在这种情况下,您最好使用HashMap 而不是MyObject

    【讨论】:

    • 如果我的数组列表包含 1000 个字符串怎么办?
    • @Marco 你的意思是 1000 列还是 1000 行?
    • 我的意思是 1000 列。姓名、姓氏、年龄、性别、身高、体重、国家、生日……
    • @Marco 对于这种情况,您还需要解析元信息,请查看更新的答案。
    • @Marco 如果你有 1000 列,我认为你不想将所有这些信息存储在一个有 1000 个设置器和 1000 个获取器的类中......
    猜你喜欢
    • 2011-11-25
    • 2020-01-11
    • 2013-08-26
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多