【发布时间】:2010-09-06 07:47:22
【问题描述】:
我有一个整数列表List<Integer>,我想将所有整数对象转换为字符串,从而完成一个新的List<String>。
当然,我可以创建一个新的 List<String> 并循环遍历每个整数调用 String.valueOf() 的列表,但我想知道是否有更好(阅读:更自动)的方法干吗?
【问题讨论】:
标签: java string collections integer
我有一个整数列表List<Integer>,我想将所有整数对象转换为字符串,从而完成一个新的List<String>。
当然,我可以创建一个新的 List<String> 并循环遍历每个整数调用 String.valueOf() 的列表,但我想知道是否有更好(阅读:更自动)的方法干吗?
【问题讨论】:
标签: java string collections integer
使用Google Collections from Guava-Project,您可以在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() 在应用于 null 时会抛出 NullPointerException,因此只有在您确定列表不包含 null 时才使用它。
【讨论】:
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方便的方法,真的吗?
【讨论】:
toString 示例来说这有点长,但对于 Guava 的函数库不支持的转换,它最终会更短。自定义函数仍然很简单,但它的代码比这个 Java 8 流要多得多
据我所知,迭代和实例化是唯一的方法。类似的东西(对于其他人可能的帮助,因为我相信你知道如何做到这一点):
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));
}
【讨论】:
您所做的很好,但如果您觉得需要“Java-it-up”,您可以使用 Transformer 和来自 Apache Commons 的 collect method,例如:
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);
【讨论】:
String.valueOf 的来源表明:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
这并不重要,但我会使用 toString。
【讨论】:
我会使用 .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());
}
【讨论】:
这是一个单线解决方案,无需使用非 JDK 库作弊。
List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
【讨论】:
另一个使用 Guava 和 Java 8 的解决方案
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));
【讨论】:
不是核心 Java,也不是泛型化的,但流行的 Jakarta commons 集合库为此类任务提供了一些有用的抽象。具体来说,看看收集方法
如果您已经在项目中使用公共集合,则需要考虑一些事项。
【讨论】:
对于在jsight的回答中关注“拳击”的人:没有。此处使用String.valueOf(Object),并且从未执行过对int 的拆箱操作。
您使用Integer.toString() 还是String.valueOf(Object) 取决于您希望如何处理可能的空值。您想抛出异常(可能),还是列表中有“空”字符串(可能)。如果是前者,你想抛出NullPointerException 还是其他类型?
另外,jsight 回复中的一个小缺陷:List 是一个接口,你不能在上面使用 new 运算符。在这种情况下,我可能会使用java.util.ArrayList,尤其是因为我们预先知道列表可能有多长。
【讨论】:
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)));
【讨论】:
@Jonathan:我可能弄错了,但我相信 String.valueOf() 在这种情况下会调用 String.valueOf(Object) 函数,而不是被装箱到 String.valueOf(int)。 String.valueOf(Object) 如果为 null,则返回“null”,如果为非 null,则调用 Object.toString(),这不应该涉及装箱(尽管显然涉及到实例化新的字符串对象)。
【讨论】:
我认为将 Object.toString() 用于除调试以外的任何目的可能是一个非常糟糕的主意,即使在这种情况下两者在功能上是等效的(假设列表没有空值)。开发人员可以在没有任何警告的情况下随意更改任何 toString() 方法的行为,包括标准库中任何类的 toString() 方法。
甚至不用担心装箱/拆箱过程带来的性能问题。如果性能很关键,只需使用数组。如果它真的很重要,请不要使用 Java。试图智取 JVM 只会让人心痛。
【讨论】:
仅供专家解答:
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 的“Sun”不合理实现)将共享相同的后备数组(来自all),所以实际上内存效率非常高,这对于长期表现。除非您当然只想保留其中一个元素...
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 仅在您对结果进行迭代时应用转换函数。
【讨论】:
你无法避免“拳击开销”; Java 的仿通用容器只能存储对象,因此您的 int 必须装箱成整数。原则上它可以避免从 Object 到 Integer 的向下转换(因为它没有意义,因为 Object 对于 String.valueOf 和 Object.toString 都足够好),但我不知道编译器是否足够聪明来做到这一点。从 String 到 Object 的转换应该或多或少是无操作的,所以我不愿意担心那个。
【讨论】:
只是为了好玩,一个使用 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 支持级别!
【讨论】:
我没有看到任何遵循空间原则的解决方案 复杂。如果整数列表有大量元素,那么它是 大问题。
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<Integer> result),那么:
List<String> ids = (List<String>) result.stream().map(intNumber -> Integer.toString(intNumber)).collect(Collectors.toList());
解决方法之一。希望这会有所帮助。
【讨论】:
我只是想提出一个面向对象的解决方案来解决这个问题。
如果你为领域对象建模,那么解决方案就在领域对象中。这里的域是我们想要字符串值的整数列表。
最简单的方法是根本不转换列表。
话虽如此,为了在不转换的情况下进行转换,请将原始 Integer 列表更改为 List of Value,其中 Value 看起来像这样......
class Value {
Integer value;
public Integer getInt()
{
return value;
}
public String getString()
{
return String.valueOf(value);
}
}
这将比复制列表更快,占用更少的内存。
祝你好运!
【讨论】: