115

我有一个整数列表,List<Integer>我想将所有整数对象转换为字符串,从而完成一个新的List<String>.

自然地,我可以创建一个新的List<String>并循环调用String.valueOf()每个整数的列表,但我想知道是否有更好的(阅读:更自动的)方法来做到这一点?

4

21 回答 21

106

使用来自 Guava-Project 的 Google Collections,您可以使用Liststransform中的方法

import com.google.common.collect.Lists;
import com.google.common.base.Functions

List<Integer> integers = Arrays.asList(1, 2, 3, 4);

List<String> strings = Lists.transform(integers, Functions.toStringFunction());

List返回的是transform支持列表上的视图- 转换将应用于对转换列表的每次访问。

请注意,当应用于 null 时Functions.toStringFunction()会抛出 a NullPointerException,因此只有在您确定列表不包含 null 时才使用它。

于 2009-08-04T12:04:09.157 回答
96

Java 8 的解决方案。比 Guava 长一点,但至少您不必安装库。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

//...

List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = integers.stream().map(Object::toString)
                                        .collect(Collectors.toList());

对于 Java 11,

List<String> strings = integers.stream().map(Object::toString)
                                        .collect(Collectors.toUnmodifiableList());

仍然没有map方便的方法,真的吗?

于 2014-04-11T23:52:19.127 回答
84

据我所知,迭代和实例化是做到这一点的唯一方法。类似的东西(对于其他人的潜在帮助,因为我相信你知道如何做到这一点):

List<Integer> oldList = ...
/* Specify the size of the list up front to prevent resizing. */
List<String> newList = new ArrayList<>(oldList.size());
for (Integer myInt : oldList) { 
  newList.add(String.valueOf(myInt)); 
}
于 2008-08-20T18:34:07.197 回答
41

你所做的很好,但如果你觉得需要“Java-it-up”,你可以使用TransformerApache Commons的collect 方法,例如:

public class IntegerToStringTransformer implements Transformer<Integer, String> {
   public String transform(final Integer i) {
      return (i == null ? null : i.toString());
   }
}

..进而..

CollectionUtils.collect(
   collectionOfIntegers, 
   new IntegerToStringTransformer(), 
   newCollectionOfStrings);
于 2008-08-21T01:24:42.687 回答
9

而不是使用 String.valueOf 我会使用 .toString(); 它避免了@johnathan.holland 描述的一些自动装箱

javadoc 说 valueOf 返回与 Integer.toString() 相同的东西。

List<Integer> oldList = ...
List<String> newList = new ArrayList<String>(oldList.size());

for (Integer myInt : oldList) { 
  newList.add(myInt.toString()); 
}
于 2008-08-20T18:45:13.113 回答
9

String.valueOf 的来源显示了这一点:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

这并不重要,但我会使用 toString。

于 2008-08-20T19:03:11.637 回答
9

这是一个单线解决方案,无需使用非 JDK 库作弊。

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
于 2011-04-25T18:42:07.420 回答
7

另一个使用 Guava 和 Java 8 的解决方案

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));
于 2014-04-25T12:38:10.050 回答
3

不是核心 Java,也不是泛型化的,但流行的 Jakarta commons 集合库对这类任务有一些有用的抽象。具体来说,看看收集方法

CollectionUtils

如果您已经在项目中使用公共集合,则需要考虑一些事情。

于 2008-08-20T20:26:04.213 回答
3

对于在jsight的回答中关注“拳击”的人:没有。String.valueOf(Object)在这里使用,并且int从未执行过拆箱。

是使用Integer.toString()还是String.valueOf(Object)取决于您希望如何处理可能的空值。您想抛出异常(可能),还是列表中有“空”字符串(可能)。如果是前者,你想抛出一个NullPointerException还是其他类型?

此外,jsight 的响应中的一个小缺陷:List是一个接口,您不能在其上使用 new 运算符。在这种情况下,我可能会使用 a java.util.ArrayList,特别是因为我们预先知道列表可能有多长。

于 2008-08-28T18:35:49.467 回答
3
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())
于 2019-06-19T11:11:06.827 回答
3

使用原始列表中的 forEach 方法的稍微更简洁的解决方案:

    List<Integer> oldList = Arrays.asList(1, 2, 3, 4, 5);
    List<String> newList = new ArrayList<>(oldList.size());
    oldList.forEach(e -> newList.add(String.valueOf(e)));
于 2020-04-15T18:56:27.870 回答
2

@Jonathan:我可能弄错了,但我相信 String.valueOf() 在这种情况下会调用 String.valueOf(Object) 函数,而不是装箱到 String.valueOf(int)。如果 String.valueOf(Object) 为 null,则返回“null”;如果为非 null,则调用 Object.toString(),这不应该涉及装箱(尽管显然涉及实例化新的字符串对象)。

于 2008-08-20T18:42:01.483 回答
2

我认为将 Object.toString() 用于除调试以外的任何目的可能是一个非常糟糕的主意,即使在这种情况下两者在功能上是等效的(假设列表没有空值)。开发人员可以在没有任何警告的情况下自由更改任何 toString() 方法的行为,包括标准库中任何类的 toString() 方法。

甚至不用担心装箱/拆箱过程带来的性能问题。如果性能很关键,只需使用数组。如果它真的很重要,请不要使用 Java。试图超越 JVM 只会导致心痛。

于 2008-08-20T18:53:35.527 回答
2

仅供专家解答:

    List<Integer> ints = ...;
    String all = new ArrayList<Integer>(ints).toString();
    String[] split = all.substring(1, all.length()-1).split(", ");
    List<String> strs = Arrays.asList(split);
于 2008-09-11T20:40:12.920 回答
2

Lambdaj允许以非常简单易读的方式做到这一点。例如,假设您有一个 Integer 列表,并且您想将它们转换为相应的 String 表示形式,您可以编写类似的内容;

List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
    public String convert(Integer i) { return Integer.toString(i); }
}

Lambdaj 仅在您对结果进行迭代时应用转换函数。

于 2010-03-07T12:40:04.090 回答
1

你无法避免“拳击开销”;Java 的仿通用容器只能存储对象,因此您的 int 必须装箱成 Integer。原则上它可以避免从 Object 到 Integer 的向下转换(因为它没有意义,因为 Object 对于 String.valueOf 和 Object.toString 都足够好),但我不知道编译器是否足够聪明来做到这一点。从 String 到 Object 的转换应该或多或少是无操作的,所以我不愿意担心那个。

于 2008-08-20T20:25:49.673 回答
0

只是为了好玩,一个使用 jsr166y fork-join 框架的解决方案,应该在 JDK7 中。

import java.util.concurrent.forkjoin.*;

private final ForkJoinExecutor executor = new ForkJoinPool();
...
List<Integer> ints = ...;
List<String> strs =
    ParallelArray.create(ints.size(), Integer.class, executor)
    .withMapping(new Ops.Op<Integer,String>() { public String op(Integer i) {
        return String.valueOf(i);
    }})
    .all()
    .asList();

(免责声明:未编译。规范未最终确定。等等)

在 JDK7 中不太可能是一些类型推断和语法糖,以使 withMapping 调用不那么冗长:

    .withMapping(#(Integer i) String.valueOf(i))
于 2008-09-14T21:25:13.147 回答
0

这是一件非常基本的事情,我不会使用外部库(它会导致您的项目中出现您可能不需要的依赖项)。

我们有一类专门用于完成此类工作的静态方法。因为这方面的代码非常简单,所以我们让 Hotspot 为我们做优化。这似乎是我最近代码中的一个主题:编写非常简单(直接)的代码,让 Hotspot 发挥它的魔力。我们很少遇到像这样的代码的性能问题——当一个新的 VM 版本出现时,您可以获得所有额外的速度优势等。

尽管我很喜欢 Jakarta 系列,但它们不支持泛型并且使用 1.4 作为 LCD。我对 Google Collections 很警惕,因为它们被列为 Alpha 支持级别!

于 2008-09-24T07:27:48.683 回答
0

我没有看到任何遵循空间复杂性原则的解决方案。如果整数列表有大量元素,那么这是个大问题。

It will be really good to remove the integer from the List<Integer> and free
the space, once it's added to List<String>.

我们可以使用迭代器来实现相同的目的。

    List<Integer> oldList = new ArrayList<>();
    oldList.add(12);
    oldList.add(14);
    .......
    .......

    List<String> newList = new ArrayList<String>(oldList.size());
    Iterator<Integer> itr = oldList.iterator();
    while(itr.hasNext()){
        newList.add(itr.next().toString());
        itr.remove();
    }
于 2017-08-29T16:27:48.840 回答
-1

我只是想用一个面向对象的解决方案来解决这个问题。

如果您为域对象建模,那么解决方案就在域对象中。这里的域是我们想要字符串值的整数列表。

最简单的方法是根本不转换列表。

话虽这么说,为了在不转换的情况下进行转换,请将原始整数列表更改为值列表,其中值看起来像这样......

class Value {
    Integer value;
    public Integer getInt()
    {
       return value;
    }
    public String getString()
    {
       return String.valueOf(value);
    }
}

这将比复制列表更快并且占用更少的内存。

祝你好运!

于 2012-09-07T17:40:15.600 回答