【问题标题】:How to convert a 2d array into a 2d ArrayList in java?如何在java中将二维数组转换为二维ArrayList?
【发布时间】:2020-10-04 08:03:13
【问题描述】:

我有一个 Java 程序,它从文件中读取元素,将它们存储在二维数组中,然后通过提交多个操作来操作它们。

我已经使用二维数组实现了程序,现在我想找到一种方法将这个数组变成二维数组列表,这样我就可以单独操作这些元素,就像我对二维数组所做的那样。

程序从如下所示的文件中读取数据:

Jason,56
Martha,89
James,23
...

这是我尝试将二维数组转换为二维数组列表的代码:

请记住,我希望将所有名称存储在数组/ArrayList 的第一列中,并将年龄存储在第二列中:

public class Testr {

    public static void main(String[] args) throws FileNotFoundException, IOException {
            Scanner sc = new Scanner(new BufferedReader(new FileReader("C:\\Users\\test.csv")));

            int num_rows = countLines("C:\\Users\\test.csv");
            System.out.println("Num of rows : " + num_rows);

            int num_cols = countColumns("C:\\Users\\test.csv");
            System.out.println("Num of cols : " + num_cols);

            String[][] Entries_arr = new String[num_rows][num_cols];
while(sc.hasNextLine())
            {
                for(int i = 0; i < Entries_arr.length; i++)
                {
                    String[] line;
                    line = sc.nextLine().trim().split(";");
                    for(int j = 0; j < line.length; j++)
                    {
                        Entries_arr[i][j] = line[j];

                    }
                }
            }
            List<List<String>> Entries = new ArrayList<List<String>>();
            for(int i = 0; i < Entries_arr.length; i++)
            {
                List<String> recs = new ArrayList<String>();
                for(int j = 0; j < Entries_arr[i].length; j++)
                {
                    recs.add(String.valueOf(Entries_arr[i][j]));
                }
                Entries.add(recs);
            }
            System.out.println(Entries);

    }
    //------------------------------------------------------------------------------------------------------------------------   
    public static int countLines(String filename) throws IOException {
    InputStream is = new BufferedInputStream(new FileInputStream(filename));
    try {
        byte[] c = new byte[1024];
        int count = 0;
        int readChars = 0;
        boolean empty = true;
        while ((readChars = is.read(c)) != -1) {
            empty = false;
            for (int i = 0; i < readChars; ++i) {
                if (c[i] == '\n') {
                    ++count;
                }
            }
        }
        return (count == 0 && !empty) ? 1 : count;
    } finally {
        is.close();
    }
}
    //------------------------------------------------------------------------------------------------------
        public static int countColumns(String filename) {
        File file = new File(filename);
        Scanner scanner;
        try {
            scanner = new Scanner(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return -1;
        }

        int number = 0;
        if (scanner.hasNextLine()) {
            number = scanner.nextLine().split(";").length;
        }
        scanner.close();
        return number;
        }
}

感谢任何帮助。

【问题讨论】:

  • 那么问题出在哪里?除了阅读之外,我没有看到你写信给Entries_arr
  • 你的输出Entries有什么问题?
  • 您不应该使用 2D 数组或 2D 列表,因为无论尝试解决方案,您都将使用并行数组或并行列表,这两者都会招致灾难。最好创建一个名为 User 的类,它在私有字段中同时保存名称 String 和年龄 int,然后创建一个实例化为 ArrayList&lt;User&gt; 的单个 List&lt;user&gt;,然后用这个单维列表填充用户对象。
  • 您的代码似乎也过于复杂了。您应该简单地创建您的列表:List&lt;User&gt; users = new ArrayList&lt;&gt;(); 然后遍历文件,从每一行创建用户对象并填充您的列表,并从每一行创建一个用户。无需创建数组,无需转换,一举搞定。
  • @DontKnowMuchButGettingBetter 谢谢你的回答,你能解释一下吗?我想做的就是像处理二维数组一样操作二维数组列表。因为这样我得到的每个条目都是这样的:[Jason,56],...

标签: java arrays string file arraylist


【解决方案1】:

回到 cmets 中指出的内容

  1. 不要使用二维数组(或二维列表),因为您将使用类似于并行数组或并行列表的数据结构。 有关详细信息,请参阅 Jon Skeet 的 Anti-Pattern: Parallel Collections 博客。
  2. 此外,通过尝试使用 2D 数组/列表来解决您的问题,您的代码会变得比实际需要的复杂得多(而且没有充分的理由)。

那么如何才能像 cmets 中指出的那样?

以下代码

  • 逐行读取测试文件,
  • 将每一行处理成一个User 实例,
  • 并将它们全部收集到ArrayList
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileToList {

    public static void main(String[] args) {
        try (Stream<String> lines = Files.lines(findCsvFile())) {
            List<User> users = lines
                    .map(FileToList::process)
                    .flatMap(Optional::stream)
                    .collect(Collectors.toCollection(ArrayList::new));

            System.out.println(users);
        } catch (Exception e) {
            System.out.println("Error when accessing the file\n");
            e.printStackTrace();
        }
    }

    static Path findCsvFile() throws Exception {
        URL resource = FileToList.class.getResource(FileToList.class.getSimpleName() + ".class");
        return Paths.get(resource.toURI()).resolveSibling("test.csv");
    }

    static Optional<User> process(String line) {
        Optional<User> user = Optional.empty();
        String[] values = line.split(",");
        try {
            String name = values[0];
            int age = Integer.parseInt(values[1]);
            User actualUser = new User(name, age);
            user = Optional.of(actualUser);
        } catch (Exception e) {
            System.out.printf("Cannot process line: \"%s\" | Error: %s\n", line, e);
        }
        return user;
    }

    static class User {
        private final String userFirstName;
        private final int userAge;

        User(String name, int age) {
            this.userAge = age;
            this.userFirstName = name;
        }

        public String getUserFirstName() {
            return userFirstName;
        }

        public int getUserAge() {
            return userAge;
        }

        @Override
        public String toString() {
            return String.format("%s(%d)", userFirstName, userAge);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            User user = (User) o;
            return userAge == user.userAge &&
                    Objects.equals(userFirstName, user.userFirstName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(userFirstName, userAge);
        }
    }
}

针对您的示例 CVS 文件运行上述代码,然后输出

[Jason(56), Martha(89), James(23)]

请注意,Optionalprocess 方法中使用仅用于涵盖无法将 CSV 文件中的行处理为新的User 对象的情况。然后.flatMap(Optional::stream) 从流中删除任何潜在的可选(不存在)用户实例,然后将实际用户收集到ArrayList 中。

【讨论】:

    猜你喜欢
    • 2020-09-10
    • 2023-04-03
    • 2020-11-15
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 2019-01-23
    相关资源
    最近更新 更多