【问题标题】:ArrayList behavior with and without adding an empty string添加和不添加空字符串的 ArrayList 行为
【发布时间】:2015-11-01 14:36:23
【问题描述】:

一个新创建的ArrayList 没有添加任何元素,看起来就像一个添加了空字符串的ArrayList

这让我觉得新创建的ArrayList 即使没有在其中添加任何元素,也有一个默认为空的string 或添加了元素。

package cracking;

import java.util.ArrayList;

public class Ask
{
    public static void main(String[] args)
    {
        ArrayList<String> al = new ArrayList<String>();
        System.out.println(al.size());//0
        System.out.println(al);//[]

        al.add("");
        System.out.println(al.size());//1
        System.out.println(al);//[]
    }
}

但是,两种情况下ArrayList 的大小差异导致它们不一致,尤其是打印出来的两个ArrayList 看起来完全一样。

为了保持一致性,我觉得两种都可以:

  1. 刚刚创建的 ArrayList 的大小,即甚至之前 向其中添加任何元素应显示 1 暗示空字符串或 元素,因为即使添加到 ArrayList 也会使其看起来相同。
  2. 不应允许打印出新创建的ArrayList,它 应该只打印 NULL 或其他内容,而不是显示 [] 之类的 现在显示

【问题讨论】:

  • 您实际上是在插入一个空的字符串对象。这将算作 ArrayList 中的一个条目,即使它在打印时没有显示为这样。请记住,空字符串与 NULL 不同。

标签: java arraylist data-structures whitespace


【解决方案1】:

您被AbstractCollectiontoString 实现所欺骗。见这里:

public String More ...toString() {
   Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

您的收藏集大小为 1,但它不打印任何内容,包括逗号字符 ,,因为它只有大小一。尝试添加 multilpe 空字符串,您会更清楚地看到结果。

al.add("");
al.add("");
al.add("");
al.add("");
al.add("");
System.out.println(al); // Prints [, , , , ]

【讨论】:

  • 这个故事的寓意是:不要依赖toString() 来确保代码的正确性。它不是为它设计的。
  • @Kon,感谢您向我展示了实现。我认为这是我困惑的根源。 if (!i.hasNext()) return "[]";但是你不认为在有空字符串和没有空字符串的情况下显示相同的输出不是一个好主意。也许他们可以输出 if (!i.hasNext()) return "";或类似的东西。你怎么看?
  • @PepperBoy 请记住,实现是inherited by ArrayList。此实现需要在所有Collection 类(SetMap 等)中保持一致。在这种情况下,实现是有意义的,因为您永远不想做类似list1.toString().equals(list2.toString()) 的事情,因为这种比较很尴尬。你更有可能想做list1.equals(list2)之类的事情。 toString() 方法旨在为对象提供有意义的表示,但不是精确唯一的表示。也就是说,两个不同的列表可能有相同的 toStrings
【解决方案2】:

[] 代表一个空列表。这是约定俗成的,但我想你会觉得这是合理的。

并且打印ArrayList 在它包含的每个对象上使用toString 来显示这些内容的打印表示。打印字符串时(使用toString),引号不包含

考虑对您的代码进行以下修改:

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

al.add("");
al.add("");
al.add("");
System.out.println(al);//[]

输出是:

[, , ]

我们不妨抱怨在打印ArrayList 时使用括号,但请注意,toString 的输出通常仅对调试有用,不应以编程方式依赖。

docstoString

一般来说,toString 方法返回一个“以文字形式表示”该对象的字符串。结果应该是一个简洁但信息丰富的表示,易于人们阅读。

在您的示例中,这确实有点崩溃:用一个空的string 打印ArrayList&lt;strin&gt; 并不是特别有用。如果您需要检查/验证收藏的内容,例如对于调试,您还应该打印length

【讨论】:

    【解决方案3】:

    ArrayList 正在使用您放入其中的对象的toString 作为其toString 调用的一部分。这对您来说看起来很奇怪的原因是打印空字符串不会打印任何内容。

    理想情况下,不会选择在列表中存储空字符串,而是会进行检查以确保只有非空字符串进入列表。

    if(!"".equals(value)) {
        al.add(value);
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 2012-11-06
      相关资源
      最近更新 更多