Converting List<Integer> to List<String>

我有一个整数列表,List<Integer>,我想把所有的整数对象转换成字符串,从而以一个新的 List<String>结束。

自然地,我可以创建一个新的 List<String>,然后循环遍历每个整数调用 String.valueOf()的列表,但是我想知道是否有更好的(读取: 更自动化)方法?

230125 次浏览

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

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));
}

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

我没有使用 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());
}

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

Don't even worry about the performance problems caused by the boxing/unboxing process. If performance is critical, just use an array. If it's really critical, don't use Java. Trying to outsmart the JVM will only lead to heartache.

String.valueOf 的源代码显示如下:

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

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

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

不是核心 Java,也不是泛型化的,但是流行的 Jakartacommons 集合库对这类任务有一些有用的抽象。上的集合方法

CollectionUtils

如果您已经在项目中使用了 commons 集合,则需要考虑的事项。

你现在做的很好,但是如果你觉得需要“ Java-it-up”,你可以使用 TransformerApache Commons中的 收集方法收集方法,例如:

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

..and then..

CollectionUtils.collect(
collectionOfIntegers,
new IntegerToStringTransformer(),
newCollectionOfStrings);

对于那些关心“拳击”的人来说,jsight 的回答是: 没有拳击。这里使用的是 String.valueOf(Object),从未执行过对 int的解压缩。

Whether you use Integer.toString() or String.valueOf(Object) depends on how you want to handle possible nulls. Do you want to throw an exception (probably), or have "null" Strings in your list (maybe). If the former, do you want to throw a NullPointerException or some other type?

Also, one small flaw in jsight's response: List is an interface, you can't use the new operator on it. I would probably use a java.util.ArrayList in this case, especially since we know up front how long the list is likely to be.

只有专家才能回答这个问题:

    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);

Just for fun, a solution using the jsr166y fork-join framework that should in 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中不太可能有类型推断和语法糖,这使得 Mapping 调用不那么冗长:

    .withMapping(#(Integer i) String.valueOf(i))

这是一个非常基本的事情,我不会使用外部库(它会在您的项目中产生一个您可能不需要的依赖项)。

We have a class of static methods specifically crafted to do these sort of jobs. Because the code for this is so simple we let Hotspot do the optimization for us. This seems to be a theme in my code recently: write very simple (straightforward) code and let Hotspot do its magic. We rarely have performance issues around code like this - when a new VM version comes along you get all the extra speed benefits etc.

尽管我很喜欢雅加达的集合,但是它们不支持泛型,并且使用1.4作为 LCD。我担心谷歌收藏,因为他们被列为阿尔法支持级别!

使用 谷歌从番石榴收集-项目,您可以在 清单类中使用 transform方法

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());

transform返回的 List是后备列表上的 风景-转换将应用于每次访问转换后的列表。

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

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 仅在迭代结果时应用转换函数。

Here's a one-liner solution without cheating with a non-JDK library.

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));

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

If you model domain objects, then the solution is in the domain objects. The domain here is a List of integers for which we want string values.

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

也就是说,为了在不转换的情况下进行转换,将原始的 Integer 列表改为 Value 列表,其中 Value 看起来像这样..。

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

This will be faster and take up less memory than copying the List.

Java8解决方案。比番石榴长一点,但至少你不必安装一个库。

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());

对于 Java11,

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

还是没有 map方便的方法,真的吗?

另一种使用 Guava 和 Java8的解决方案

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));

我没有看到任何遵循空间原理的解决方案 如果整数列表有大量的元素,那么它的 big problem.

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();
}
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())

A slightly more concise solution using the forEach method on the original list:

    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)));