将列表转换为字符串的最佳方法是什么<String>



所以我一直在回顾我大约一年半前编写的代码,试图修复它,我发现这个函数让我感到困惑。我搜索了一种做同样事情的方法,并找到了一个相当不错的功能,我很好奇什么会更好。

函数 A:

public static String listToString(List<String> list){
    StringBuilder sb = new StringBuilder();
    if (list != null && list.size() > 1){
        sb.append(list.get(0));
        for (int i = 1; i < list.size(); i++){
            sb.append(", " + list.get(i));
        }
    }else if(list != null && (list.size() == 1)){
        sb.append(list.get(0));
    }
    return sb.toString();
}

函数 B:

public static String listToString(List<String> list) {
    String str = "";
    for (String s : list) {
        str += s + ", ";
    }
    return str;
}

现在我在学习Java的头几个月内编写了函数A,所以我可能不是最好的,尽管有什么理由我应该坚持这种方法吗?

检查番石榴上的木匠

    String s= Joiner.on(",").join(lists);

检查下面的输出测试

    List<String> lists=new ArrayList<String>();
    lists.add("a1");
    lists.add("a2");
    lists.add("a3");
    lists.add("a4");
    String s = Joiner.on(",").join(lists);
    System.out.println(s);

输出:

a1,a2,a3,a4

Apache 的 commons lang,只是附加

 StringUtils.join(list);

或 按字符分隔。

StringUtils.join(java.lang.Iterable,char)

Java 8.0 及以上,第一个参数是分离元素

String joined = String.join("", list);

函数 A 更可取,因为它只使用 StringBuilder 的一个实例,而函数 B 中的代码在循环中执行

str += s + ", ";

相当于

str = new StringBuilder(str).append(s).append(", ").toString();

因此,在每次迭代中,您必须:

  • 创建新的字符串生成器
  • 将当前字符串的内容复制到此字符串生成器
  • 现在,您可以添加", "s
  • 根据 StringBuilder 的当前内容创建并返回新字符串

(所以在每次迭代中,你需要一次又一次地读取整个字符串......)而在场景B中,你只专注于向单个StringBuilder添加新字符


无论如何,从Java 8开始,你不需要把太多精力放在可以连接字符串集合的编写方法上。您可以简单地使用StringJoiner类或更简单的调用
join(CharSequence delimiter, Iterable<? extends CharSequence> elements) 字符串类中的方法,它将为您使用 StringJoiner。此方法的代码如下所示:

public static String join(CharSequence delimiter,
        Iterable<? extends CharSequence> elements) {
    Objects.requireNonNull(delimiter);
    Objects.requireNonNull(elements);
    StringJoiner joiner = new StringJoiner(delimiter);
    for (CharSequence cs: elements) {
        joiner.add(cs);
    }
    return joiner.toString();
}

请注意,Objects.requireNonNull(delimiter); 会在 null 的情况下抛出 NPE,所以如果你想避免它,你可以编写你自己的此方法版本,并用更类似的东西替换这个测试。

if (delimiter==null || elements==null) return "";

或者,如果您希望允许分隔符为空

if (elements==null) return "";
if (delimiter == null) delimiter = "";//use empty string as delimiter 

除了使用库之外,您还可以使用

(我最常看到的模式)

public static String listToString(List<String> list) {
    StringBuilder sb = new StringBuilder();
    boolean first = true;
    for (String string : list) {
        if (first)
            first = false;
        else
            sb.append(", ");
        sb.append(string);
    }
    return sb.toString();
}

(也很常见)

public static String listToString(List<String> list) {
    StringBuilder sb = new StringBuilder();
    String separator = "";
    for (String string : list) {
        sb.append(separator).append(string);
        separator = ", ";
    }
    return sb.toString();
}

(最短,有点难读)

public static String listToString(List<String> list) {
    StringBuilder sb = new StringBuilder();
    for (Iterator<String> iterator = list.iterator(); iterator.hasNext();)
        sb.append(iterator.next()).append(iterator.hasNext() ? ", " : "");
    return sb.toString();
}

(可能是最快的,因为循环中没有额外的条件跳转)

public static String listToString(List<String> list) {
    StringBuilder sb = new StringBuilder();
    Iterator<String> iterator = list.iterator();
    if (iterator.hasNext()) {
        sb.append(iterator.next());
        while (iterator.hasNext())
            sb.append(", ").append(iterator.next());
    }
    return sb.toString();
}

或者其他可读和简短的东西,如B,但使用StringBuilder。您不希望在循环中+字符串串联。这将创建临时对象。

最新更新