提问人:ChrisThomas123 提问时间:8/21/2008 最后编辑:Joris SchellekensChrisThomas123 更新时间:8/7/2023 访问量:241231
将 List<Integer> 转换为 List<String>
Converting List<Integer> to List<String>
问:
我有一个整数列表,我想将所有整数对象转换为字符串,从而以新的 .List<Integer>
List<String>
当然,我可以创建一个新的并遍历调用每个整数的列表,但我想知道是否有更好的(阅读:更自动)的方法?List<String>
String.valueOf()
答:
据我所知,迭代和实例化是唯一的方法。像这样的东西(对于其他人潜在的帮助,因为我相信你知道该怎么做):
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() 用于调试以外的任何目的可能是一个非常糟糕的主意,即使在这种情况下两者在功能上是等价的(假设列表没有空值)。开发人员可以自由地更改任何 toString() 方法的行为,而无需任何警告,包括标准库中任何类的 toString() 方法。
甚至不用担心装箱/拆箱过程引起的性能问题。如果性能至关重要,只需使用数组即可。如果它真的很关键,就不要使用 Java。试图智取JVM只会导致心痛。
String.valueOf 的源代码如下所示:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
这并不重要,但我会使用 toString。
你无法避免“拳击开销”;Java 的仿泛型容器只能存储对象,因此必须将整数装箱到整数中。原则上,它可以避免从 Object 到 Integer 的下沉(因为它毫无意义,因为 Object 对 String.valueOf 和 Object.toString 都足够好),但我不知道编译器是否足够聪明来做到这一点。从 String 到 Object 的转换应该或多或少是空操作,所以我不愿意担心这个问题。
评论
不是核心 Java,也不是通用的,但流行的 Jakarta commons 集合库为此类任务提供了一些有用的抽象。具体来说,请看一下
如果您已经在项目中使用共享资源集合,请考虑以下事项。
评论
你正在做的事情很好,但如果你觉得需要“Java-it-up”,你可以使用Transformer和Apache 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);
评论
对于jsight中关心“拳击”的人的回答:没有。 在此处使用,并且从未执行过拆箱操作。String.valueOf(Object)
int
是否使用 或 取决于要如何处理可能的 null。您是想抛出异常(可能),还是列表中有“null”字符串(可能)。如果是前者,你想扔一个还是其他类型?Integer.toString()
String.valueOf(Object)
NullPointerException
另外,jsight 的响应中有一个小缺陷:是一个接口,你不能在上面使用 new 运算符。在这种情况下,我可能会使用 a,特别是因为我们预先知道列表可能有多长。List
java.util.ArrayList
仅供专家回答:
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);
评论
String
all
只是为了好玩,一个使用 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))
这是一件非常基本的事情,我不会使用外部库(这会导致您的项目中出现您可能不需要的依赖关系)。
我们有一类专门用于执行此类工作的静态方法。因为这个代码非常简单,所以我们让Hotspot为我们做优化。这似乎是我最近代码中的一个主题:编写非常简单(直接)的代码,让 Hotspot 发挥它的魔力。我们很少遇到这样的代码性能问题 - 当新的 VM 版本出现时,您将获得所有额外的速度优势等。
尽管我非常喜欢 Jakarta 系列,但它们不支持泛型并使用 1.4 作为 LCD。我对 Google Collections 持谨慎态度,因为它们被列为 Alpha 支持级别!
使用 Guava-Project 的 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());
返回的 by 是后备列表上的视图 - 转换将应用于对转换列表的每次访问。List
transform
请注意,当应用于 null 时会抛出 a,因此只有在确定列表不包含 null 时才使用它。Functions.toStringFunction()
NullPointerException
评论
new ArrayList<>(Lists.transform(integers, Functions.toStringFunction()))
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 仅在您迭代结果时应用转换函数。
这是一个单行解决方案,不会使用非 JDK 库作弊。
List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
我只是想用一个面向对象的解决方案来解决这个问题。
如果对域对象进行建模,则解决方案位于域对象中。这里的域是我们需要字符串值的整数列表。
最简单的方法是根本不转换列表。
话虽如此,为了在不转换的情况下进行转换,请将原始的 Integer 列表更改为 List of Value,其中 Value 如下所示......
class Value {
Integer value;
public Integer getInt()
{
return value;
}
public String getString()
{
return String.valueOf(value);
}
}
与复制列表相比,这将更快,占用的内存更少。
Java 8 的解决方案。比番石榴的要长一点,但至少你不必安装库。
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
评论
toString
使用 Guava 和 Java 8 的另一种解决方案
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));
我没有看到任何遵循空间原理的解决方案 复杂性。如果整数列表包含大量元素,则它是 大问题。
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())
评论
使用原始列表上的 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)));
Java 8 的解决方案。比番石榴长一点,但至少你 不必安装库。
以防万一,对于那些使用 >= 16 版本的 Java 的幸运儿来说,不再需要冗长的调用链,只需使用 Stream 接口 toList
中的新方法即可:.collect(Collectors.toList())
List<String> strings = integers.stream().map(String::valueOf).toList();
所以,现在它甚至比番石榴版本还要短:)
评论