Java 通过读取同时具有动态数组作为其字段的文件来创建对象

Java 通过读取同时具有动态数组作为其字段的文件来创建对象,java,arrays,arraylist,Java,Arrays,Arraylist,我有一个包含购买信息的文本文件,它的结构如下 Mary gold 26.01.2020 Sweater 1 Jeans 2 Eve silver 20.02.2020 Sweater 2 Jeans 1 Steve bronze 19.01.2020 Jeans 2 Sweater 3 CustomerName选项卡MembershipType选项卡ShoppingDate选项卡ProductName选项卡Quantity换行符 客户可以一次购

我有一个包含购买信息的文本文件,它的结构如下

Mary    gold    26.01.2020  Sweater 1   Jeans   2
Eve silver  20.02.2020  Sweater 2   Jeans   1
Steve   bronze  19.01.2020  Jeans   2   Sweater 3
CustomerName选项卡MembershipType选项卡ShoppingDate选项卡ProductName选项卡Quantity换行符

客户可以一次购买多个不同的对象,因此ProductName和Quantity可以像这样出现多次

Mary    gold    26.01.2020  Sweater 1   Jeans   2
Eve silver  20.02.2020  Sweater 2   Jeans   1
Steve   bronze  19.01.2020  Jeans   2   Sweater 3
我目前正试图从这些数据创建一个customers对象,这里是我的实现

导入java.io.File;
导入java.io.FileNotFoundException;
导入java.text.DecimalFormat;
导入java.text.NumberFormat;
导入java.text.ParseException;
导入java.text.simpleDataFormat;
导入java.util.Date;
导入java.util.Scanner;
公共班机{
公共静态void main(字符串[]args)抛出FileNotFoundException、ParseException{
Scanner shoppingList=新扫描仪(新文件(“shoppingList.txt”);
shoppingList.useDelimiter(“[\t\n]”);
客户[]客户=新客户[0];
while(shoppingList.hasNext()){
字符串customerName=shoppingList.next();
字符串customerMembershipType=shoppingList.next();
字符串purchaseDate=shoppingList.next();
SimpleDataFormat格式化程序=新的SimpleDataFormat(“dd.MM.yyyy”);
日期=格式化程序.parse(purchaseDate);
String[]productNameList=新字符串[0];
int[]quantityList=新int[0];
while(shoppingList.hasNext()){
//这就是我卡住的地方
}
Customer[]newCustomer=新客户(customerName、customerMembershipType、purchaseDate、productNameList、quantityList);
customers=addCustomer(customers,newCustomer);
}
}
私有静态客户[]添加客户(客户[]客户,客户客户加载){
客户[]新客户=新客户[customers.length+1];
System.arraycopy(客户,0,新客户,0,客户.长度);
newCustomers[newCustomers.length-1]=CustomerLoadd;
返回新客户;
}
静态类客户{
受保护的字符串客户名称;
受保护的字符串customerMembershipType;
受保护日期购买日期;
受保护的字符串[]列表;
受保护的int[]数量列表;
公共客户(字符串customerName、字符串customerMembershipType、日期purchaseDate、字符串[]productNameList、int[]quantityList){
this.customerName=客户名称;
this.customerMembershipType=customerMembershipType;
this.purchaseDate=purchaseDate;
this.productNameList=productNameList;
this.quantityList=quantityList;
}
}

基本上,我想创建可以保存产品名称列表及其数量列表的客户对象,但由于数组是不可变的,客户可以购买无限量的产品类型,因此,如果不使用ArrayList,我找不到解决方案,但我无法在此任务中使用它。此时我能做些什么?

我建议使用ArrayList代替ArrayList尝试读取客户行并解析这些行时,需要单独执行,即以行的形式读取行,每个客户一行,然后根据逻辑解析行

如下所示(注意,我更改了客户表示,客户现在是列表而不是数组):

导入java.io.BufferedReader;
导入java.io.File;
导入java.io.FileReader;
导入java.io.IOException;
导入java.text.ParseException;
导入java.text.simpleDataFormat;
导入java.util.*;
公共班机{
公共静态void main(字符串[]args)引发IOException、ParseException{
BufferedReader=new BufferedReader(新文件阅读器(新文件(“shoppingList.txt”));
列出客户=新建ArrayList();
for(String line=reader.readLine();line!=null;line=reader.readLine()){
扫描仪购物清单=新扫描仪(行);
字符串customerName=shoppingList.next();
字符串customerMembershipType=shoppingList.next();
字符串purchaseDate=shoppingList.next();
SimpleDataFormat格式化程序=新的SimpleDataFormat(“dd.MM.yyyy”);
日期=格式化程序.parse(purchaseDate);
客户=新客户(客户名称、客户成员装运类型、日期);
while(shoppingList.hasNext()){
customer.addProduct(shoppingList.next(),shoppingList.nextInt());
}
}
}
静态类客户{
受保护的字符串客户名称;
受保护的字符串customerMembershipType;
受保护日期购买日期;
受保护的映射产品=新的HashMap();
公共客户(字符串customerName、字符串customerMembershipType、日期purchaseDate){
this.customerName=客户名称;
this.customerMembershipType=customerMembershipType;
this.purchaseDate=purchaseDate;
}
public void addProduct(字符串名称,整数数量){
产品。放置(名称、数量);
}
}
}

我能想到的最简单的解决方案是:创建一个更大的新数组(比方说是旧数组的两倍)当旧的已满,然后将元素复制到新数组。

像这样逐项读取信息有两个问题:你不知道购物清单中包含多少你已经发现的东西,但更糟糕的是:你不知道购物清单的结尾和新客户的数据的开始

所以我要做的是逐行读取文件,然后用分隔符分割行

    while (shoppingList.hasNextLine()) {
        String line = shoppingList.nextLine();
        String[] lineItems = line.split("\t");

        String customerName = lineItems[0];
        String customerMembershipType = lineItems[1];
        String purchaseDate = lineItems[2];
        // and so on
现在,您知道,在前3项之后,其余的项是产品名称和数量。您可以使用
行项的大小来计算有多少产品:

        int productCount = (lineItems.length - 3)/2;
        String[] productNameList = new String[productCount];
        int[] quantityList = new int[productCount];
现在,将值添加到这些数组对于循环来说很简单:

        int itemIndex = 3;
        for (int i = 0; i < productCount; i++) {
            productNameList[i] = lineItems[itemIndex];
            itemIndex = itemIndex + 1; // advance to next item in the line

            quantityList[i] = Integer.parseInt(lineItems[itemIndex]);
            itemIndex = itemIndex + 1; // advance to next item in the line
        }
int itemIndex=3;
for(int)