【问题标题】:Is there any way to reuse an arraylist in java? [duplicate]有没有办法在java中重用arraylist? [复制]
【发布时间】:2018-02-04 03:18:47
【问题描述】:

我有两个 ArrayLists 。我只想重用第二个数组列表(temporaryArrayList)。请注意我的代码。希望你当然会明白我想让你知道的。

    ArrayList<ArrayList<String>> arrayListContainer = new ArrayList<>();
    ArrayList<String> temporaryArrayList = new ArrayList<>();

    temporaryArrayList.add("I");
    temporaryArrayList.add("you");
    temporaryArrayList.add("he");
    temporaryArrayList.add("she");
    temporaryArrayList.add("we");

    arrayListContainer.add(temporaryArrayList);

    temporaryArrayList.clear();

    temporaryArrayList.add("Rahim");
    temporaryArrayList.add("jon");
    temporaryArrayList.add("don");
    temporaryArrayList.add("shaila");

    arrayListContainer.add(temporaryArrayList);
    temporaryArrayList.clear();


    System.out.println(arrayListContainer.size());

代码给出了 arrayListContainer 的预期大小,但没有给出预期的结果

System.out.println(arrayListContainer.get(0).get(0));

我怎样才能做到这一点。任何形式的回复或建议都将被接受。

【问题讨论】:

  • 你期待System.out.println(arrayListContainer.get(0).get(0));给你什么?
  • 为什么要重新使用temporaryArrayList?正如答案所指出的那样,无论如何您都必须复制它。所以没有任何节省,只有更多的混乱。
  • 我的项目需要一个arraylist类型的arraylist ..
  • 查看我的答案 - 将临时 ArrayList 的创建提取到一个方法并调用该方法来创建您要添加到 arrayListContainer 的每个 ArrayList。

标签: java arraylist


【解决方案1】:

您正在添加相同的对象并同时删除它。 为了将不同的临时列表添加到arrayListContainer,您应该创建一个副本:

更改执行以下操作的行:

arrayListContainer.add(temporaryArrayList);

到:

ArrayList<String> copy = new ArrayList<>(temporaryArrayList)
arrayListContainer.add(copy);

另一个选项,正如 Thilo 在下面的评论中建议的那样,每次都创建一个新的 temporaryArrayList,这样您就可以确保将 不同 临时列表添加到 arrayListContainer

【讨论】:

  • ... 或者一开始就不要重用temporaryArrayList。干净多了。
【解决方案2】:

您需要在添加时创建 ArrayList 的克隆,否则当您删除内容时,您将删除刚刚添加的实际列表的内容。克隆它将添加 ArrayList 的副本,而不是原来的。

编辑:实际上 - 基于 Thilo 对另一个答案的评论 - 更好的解决方案是将临时 ArrayList 代码提取到一个方法并调用它:

 public static void main(String[] args){

    ArrayList<ArrayList<String>> arrayListContainer = new ArrayList<>();

    String[] a = {"I","you","he"};
    arrayListContainer.add(createArrayList(a));
    String[] b = {"Bob","Rahim","Betty"};
    arrayListContainer.add(createArrayList(b));

    System.out.println(arrayListContainer.size());
    System.out.println(arrayListContainer.get(0).get(0));
 }

 private static ArrayList<String> createArrayList(String[] arr) {
     ArrayList<String> temporaryArrayList= new ArrayList<>();
     for(String str : arr) {
         temporaryArrayList.add(str);
     }
     return temporaryArrayList;
 }

【讨论】:

    【解决方案3】:

    其他答案是正确的。你正在重复使用你的第二个ArrayList,只是没有按照你想要的方式。

    您需要了解 (a) 对对象的引用,以及 (b) ArrayList 是一个对象,它是对其他对象的引用的容器。

    让我们看看代码执行期间的状态。

    首先实例化一个ArrayList,默认为十个槽。将持有对持有对String 对象的引用的其他ArrayList 实例的引用。

    ArrayList< ArrayList< String > > arrayListContainer = new ArrayList<>();
    

    ArrayList< String > temporaryArrayList = new ArrayList<>() ;
    

    实例化String 对象,在第二个列表的插槽中添加对每个对象的引用。请记住,该列表包含对String 对象的引用,而不是对象本身。

    temporaryArrayList.add( "I" ) ;
    temporaryArrayList.add( "you" ) ;
    temporaryArrayList.add( "he" ) ;
    temporaryArrayList.add( "she" ) ;
    temporaryArrayList.add( "we" ) ;
    

    将第二个列表的引用添加到第一个列表的第一个槽中。

    arrayListContainer.add(temporaryArrayList) ;
    

    通过调用clear() 删除对带有代词的String 对象的所有引用。那些String 对象实际上在内存中存在了一段时间,成为垃圾回收的候选对象,因为它们没有被任何其他对象引用。所以我们将它们显示为在这张图中消失了,但实际上它们可能会在内存中漂浮一段时间。

    temporaryArrayList.clear() ;
    

    实例化一些新的String 对象。在我们的第二个列表的插槽中添加对每个的引用。

    temporaryArrayList.add( "Rahim" ) ;
    temporaryArrayList.add( "jon" ) ;
    temporaryArrayList.add( "don" ) ;
    temporaryArrayList.add( "shaila" ) ;
    

    这是您的误解出现的地方。您显然想保留代词并在它们旁边添加一些专有名称。但是第一个列表不包含对String 对象的引用,它包含对ArrayListString 对象的引用。所以我们结束了对同一个 ArrayList 对象的两个引用,其中包含对专有名称字符串的引用。旧的代词字符串可能会或可能不会在记忆中漂浮,但我们无法再接触它们,所以我们认为它们已经消失了。

    arrayListContainer.add( temporaryArrayList ) ;
    

    接下来,您清除唯一的字符串列表。所以现在第一个ArrayList 持有对同一个现在空的第二个ArrayList 的两个引用。

    temporaryArrayList.clear() ;
    

    你最终得到一个包含两个元素的列表,其中每个元素都指向同一个空的“临时”列表。

    如果您想在第一个列表中累积字符串,请将第一个列表重新定义为 ArrayListString 而不是 ArrayList&lt;String&gt;。所以,而不是这个:

    ArrayList< ArrayList< String > > arrayListContainer = new ArrayList<>() ;
    ArrayList< String > temporaryArrayList = new ArrayList<>() ;
    …
    arrayListContainer.add( temporaryArrayList ) ;
    

    …这个,把add改成addAll

    ArrayList< String > arrayListContainer = new ArrayList<>() ;
    ArrayList< String > temporaryArrayList = new ArrayList<>() ;
    …
    arrayListContainer.addAll( temporaryArrayList ) ;  // Call `addAll` to add the elements of one collection to another collection.
    

    提示:尽可能使用接口。

    通常最好指定更通用的接口而不是具体的类,这样你就可以更容易地切换出具体的类;所以你可以使用List:List&lt; List&lt;String&gt; &gt;

    List<List<String>> listContainer = new ArrayList<>();
    

    【讨论】:

      【解决方案4】:
          ArrayList<ArrayList<String>> arrayListContainer = new ArrayList<>();
          ArrayList<String> temporaryArrayList = new ArrayList<>();
      
          temporaryArrayList.add("I");
          temporaryArrayList.add("you");
          temporaryArrayList.add("he");
          temporaryArrayList.add("she");
          temporaryArrayList.add("we");
      
          arrayListContainer.add(new ArrayList<>(temporaryArrayList));
      
         temporaryArrayList.clear();
      
          temporaryArrayList.add("Rahim");
          temporaryArrayList.add("jon");
          temporaryArrayList.add("don");
          temporaryArrayList.add("shaila");
      
          arrayListContainer.add(new ArrayList<>(temporaryArrayList));
          temporaryArrayList.clear();
      
      
          System.out.println(arrayListContainer.get(0).get(0));
      

      这只是克隆对象的另一种自然方式:)

      【讨论】:

        【解决方案5】:

        你不能以你想要的方式重复使用它。您的ArrayList&lt;ArrayList&lt;String&gt;&gt; 包含对对象的引用(在本例中,是对ArrayList&lt;String&gt; 的引用)。如果你说

        arrayListContainer.add(temporaryArrayList);
        

        以后,

        arrayListContainer.add(temporaryArrayList);
        

        如果没有在两者之间为temporaryArrayList 分配新值,您的arrayListContainer 将有两个对同一个对象的引用。 temporaryArrayList 是对对象的引用,即使对象的内容发生变化,它也不会改变(除非你重新分配一个全新的对象给它)。

        您需要创建一个新对象。

        【讨论】:

          【解决方案6】:

          在您的情况下,您不需要数组列表的数组列表,只需将其设为字符串数组的数组列表:

          ArrayList<String[]> arrayContainer = new ArrayList<>();
          

          添加完字符串后,调用:

          arrayContainer.add(temporaryArrayList.toArray(new String[temporaryArrayList.size()]));
          

          这样您就可以安全地重用临时数组列表。

          【讨论】:

            猜你喜欢
            • 2014-07-04
            • 2010-10-18
            • 2022-12-05
            • 1970-01-01
            • 2016-07-10
            • 2017-12-23
            • 2013-08-12
            • 2017-12-12
            • 1970-01-01
            相关资源
            最近更新 更多