Java ArrayList的奇怪行为

Java ArrayList的奇怪行为,java,arraylist,Java,Arraylist,我正在使用csv文件构建一个基本数据库,当我遇到一些奇怪的事情时,我正在测试select函数 private ArrayList<Record> selectField(String selectTerm) { Log.log("Selection " + selectTerm,2,"DB_io"); ArrayList<Record> ret = new ArrayList<Record>(); if (titleRow.valu

我正在使用csv文件构建一个基本数据库,当我遇到一些奇怪的事情时,我正在测试select函数

private ArrayList<Record> selectField(String selectTerm)
{
    Log.log("Selection " + selectTerm,2,"DB_io");

    ArrayList<Record> ret = new ArrayList<Record>();

    if (titleRow.values.contains(selectTerm))
    {
        Log.log("Adding values to " + selectTerm);
        int ordinal = titleRow.values.indexOf(selectTerm);
        Log.log("Ordinal " + ordinal);
        List<String> tempList = new ArrayList<String>();

        for (Record r : data)
        {
            List<String> tempList = new ArrayList<String>();
            tempList.add(r.values.get(ordinal));
            Record s = new Record(tempList);
            ret.add(s);
            tempList.clear();
        }

        Log.log("Number of records in ret " + ret.size());
        for (Record t : ret)
        {
            Log.log(t.toString());
        }

    }
    else
    {
        Log.log("keyField does not contain that field");
        return null;
    }

    Log.log("Values " + ret.toString());
    return ret;
}
private ArrayList selectField(字符串selectTerm)
{
Log.Log(“Selection”+selectTerm,2,“DB_io”);
ArrayList ret=新的ArrayList();
if(titleRow.values.contains(selectTerm))
{
Log.Log(“向“+selectTerm”添加值);
int ordinal=标题row.values.indexOf(selectTerm);
Log.Log(“序号”+序号);
List templast=new ArrayList();
用于(记录r:数据)
{
List templast=new ArrayList();
add(r.values.get(序号));
记录s=新记录(圣堂武士);
ret.add(s);
圣殿骑士;
}
Log.Log(“ret中的记录数”+ret.size());
for(记录t:ret)
{
Log.Log(t.toString());
}
}
其他的
{
Log.Log(“keyField不包含该字段”);
返回null;
}
Log.Log(“值”+ret.toString());
返回ret;
}
当我这样做时,它记录t.ToString()的部分显示记录为空,而如果我在templast.clear()之前记录它,它显示记录包含它应该包含的数据

如果我将templast声明移动到Record r:data循环中,那么它可以正常工作,而Record t:ret循环可以正常输出记录的内容

为什么会这样

编辑:记录类

public class Record
{
    List<String> values = new ArrayList<String>();

    public Record(List<String> terms)
    { 
        this.values = terms;
    }

    public Record(String[] s)
    {
        this.values = Arrays.asList(s);
    }

    public String toString()
    {
        return values.toString();
    }
}
公共类记录
{
列表值=新的ArrayList();
公共记录(列表术语)
{ 
这个值=术语;
}
公共记录(字符串[]s)
{
this.values=Arrays.asList;
}
公共字符串toString()
{
返回值。toString();
}
}

您的
记录
实例包含对传递给其构造函数的
数组列表
实例的引用。因此,当您调用
templast.clear()
时,您将清除
记录
实例所引用的同一个
列表


您不应该调用
templast.clear()
,因为您在循环的每次迭代中都要创建一个新的
ArrayList

您的
记录
实例包含对传递给其构造函数的
ArrayList
实例的引用。因此,当您调用
templast.clear()
时,您将清除
记录
实例所引用的同一个
列表


您不应该调用
templast.clear()
,因为您在循环的每次迭代中都要创建一个新的
ArrayList

您从多个位置引用对象,clear方法通过将其引用设置为null来清理对象:


而不是
ret.add(s)
您可以使用
ret.add(s.clone())

您正在从多个位置引用对象,而clear方法正在通过将其引用设置为null来清理对象:


而不是
ret.add(s)
您可以使用
ret.add(s.clone())

所以这就是为什么,我想避免每次迭代都创建一个新的arraylist,然后在记录中创建一个新的arraylist,但我想这就是原因impossible@DuskFall您必须为每个
记录
实例创建不同的
ArrayList
实例(无论您是从外部将其传递给
记录
实例,还是在
记录
类中创建它)。这是否意味着,按照我目前的方式,我将在内存中得到两个列表实例?还是tempList包含数据,然后在记录中只包含对tempList的引用?@Dashfall
list values=new ArrayList();
是多余的,因为您正在覆盖构造函数中的实例变量,所以您正在创建一个永远不会使用的空ArrayList实例。如果要在类中创建实例,请将构造函数的主体更改为
this.values.addAll(terms);
。这样,您的外部循环就不必在每次迭代中创建一个新的ArrayList-在循环之前创建一个ArrayList并在每次迭代中调用clear就足够了。这就是我想要做的,谢谢,我会更新它。这就是为什么,我希望避免每次迭代都创建一个新的ArrayList,然后在每次迭代中创建一个新的ArrayList副记录,但我想那是impossible@DuskFall必须为每个
Record
实例创建不同的
ArrayList
实例(无论是从外部传递到
Record
实例,还是在
Record
类内部创建)。这是否意味着,按照我目前的方式,我将在内存中得到两个列表实例?还是tempList包含数据,然后在记录中只包含对tempList的引用?@Dashfall
list values=new ArrayList();
是多余的,因为您正在覆盖构造函数中的实例变量,所以您正在创建一个永远不会使用的空ArrayList实例。如果要在类中创建实例,请将构造函数的主体更改为
this.values.addAll(terms);
。这样,您的外部循环就不必在每次迭代中创建一个新的ArrayList-在循环之前创建一个ArrayList并在每次迭代中调用clear就足够了。这就是我想要做的,谢谢,我会更新它