将List<Integer>转换为List<String>

120

我有一个整数列表, List<Integer>,我想将所有整数对象转换为字符串,最终得到一个新的 List<String>

当然,我可以创建一个新的 List<String> 并循环遍历该列表,对每个整数调用 String.valueOf(),但我想知道是否有更好(即:更自动化)的方法来完成这个任务?

22个回答

107

通过使用Guava项目的Google Collections,你可以在Lists类中使用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是对原始列表的视图 - 在访问转换后的列表时将应用转换。请注意,当应用于空值时,Functions.toStringFunction()会抛出NullPointerException异常,因此仅在确定列表不包含空值时才使用它。

1
如果除了Functions.toStringFunction()之外还有更多的预定义函数,那就太好了。 - ThiamTeck
1
干净但可能不够快...每个值多一个函数调用? - h3xStream
3
HotSpot可以内联函数调用 - 因此,如果它被频繁调用,就不应该产生任何差异。 - Ben Lings
4
我不会对这个进行负评,因为它确实是一个解决方案。但鼓励人们添加库依赖以解决如此简单的任务对我来说是不能接受的。 - estani
1
这样做的一个潜在问题是转换被惰性地应用(可能多次)。为了避免这种情况,您可能希望返回 new ArrayList<>(Lists.transform(integers, Functions.toStringFunction())) - JRA_TLL
如果您在寻找字符串转数字的问题上遇到了困难,可以使用以下代码:Lists.transform(listOfStrings, Ints.stringConverter()); - LateralFractal

107

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 的便捷方法,真的吗?


1
虽然这个 toString 示例有点长,但对于 Guava Functions 库不支持的转换来说,它最终变得更短。自定义函数仍然很容易,但它需要比 Java 8 stream 更多的代码。 - lightswitch05
1
这里也有“反向”的方法,供未来的读者参考。感谢trejkaz! Collection<String> keys = blah blah blah; Collection<Integer> keyInts = keys.stream().map(Integer::parseInt).collect(Collectors.toList()); - granadaCoder

83
据我所知,迭代和实例化是唯一的做法。类似这样(对于其他可能需要帮助的人,因为我相信你知道如何做到这一点):
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)); 
}

1
原帖的作者似乎表明他已经考虑过这个解决方案,但认为这个解决方案太复杂或繁琐了。但我很难想象还有什么比这更容易的解决方法。是的,有时候你必须写3或4行代码来完成工作。 - Jay
但这会将您绑定到ArrayList。是否可以使用与原始列表相同的实现来完成此操作? - alianos-
@Andreas oldList.getClass().newInstance() 将会执行。 - Lluis Martinez

41

你现在的做法是正确的,但如果你想要“Java化”一下可以使用Transformercollect方法,它们来自于Apache Commons,例如:

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

1
CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer());但是,StringValueTransformer使用了String.valueOf... - Kannan Ekanath
5
除非对 Apache Collections 进行了新的工作,否则它们不支持泛型。 - KitsuneYMG
1
这真的是在简化Java。这不是惯用的Java,更像函数式编程。也许当我们在Java 8中获得闭包时,你可以称其为惯用的Java。 - Christoffer Hammarström
你一定要使用Collections4(而不是旧的3.x Collections),以支持泛型:https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html#transform%28java.util.Collection,%20org.apache.commons.collections4.Transformer%29 - JRA_TLL
定义一个新类只是为了“更OOP或惯用”...我不认为这比简单的for-each循环更好。它需要更多的代码并将功能移开(可以通过匿名类来减轻,但仍然是如此)。当有一个像函数式语言一样良好的语法(即Java 8以后的lambda表达式)时,这种函数式风格才开始变得有用,就像函数式语言提供了几十年一样。 - TheOperator

9
这是一个不使用非JDK库欺骗的一行解决方案。
List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));

9

我会建议使用.toString()代替String.valueOf; 这可以避免@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()); 
}

正如Tom Hawtin在“获胜的”答案中指出的那样,List<String>不能被实例化,因为它只是一个接口。 - Stu Thompson
哈,我就知道。只是我在不试用的情况下编写了代码。我会在我的答案中修正它。 - ScArcher2

9
String.valueOf的源代码如下所示:
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

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


7

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

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

4
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())

@RequiresApi(api = Build.VERSION_CODES.N) - Adnan
@Adnan,你可能在指Android的使用。但是,OP是在一般情况下提问。因此,Java 8+应该足够了。 - Kathir

4
针对关心 jsight 答案中的“boxing”问题的人:这里没有。使用的是 String.valueOf(Object),并且从未执行过将 int 拆箱。
你使用 Integer.toString() 还是 String.valueOf(Object) 取决于你如何处理可能的 null 值。你想抛出异常(可能),还是在列表中有“null”字符串(也许)。如果是前者,你想抛出 NullPointerException 还是其他类型的异常?
此外,jsight 的回答有一个小缺陷: List 是一个接口,不能在它上面使用 new 运算符。在这种情况下,我可能会使用 java.util.ArrayList,特别是因为我们事先知道列表可能的长度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接