我有一个整数列表, 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<String>(oldList.size()) 
for (Integer myInt : oldList) { 
  newList.add(String.valueOf(myInt)); 
}

其他提示

使用 Guava-Project 的 Google Collections, ,你可以使用 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());

List 由返回 transform 是一个 看法 在支持列表上 - 转换将应用于对转换列表的每次访问。

意识到 Functions.toStringFunction() 会抛出一个 NullPointerException 当应用于 null 时,因此仅当您确定列表不包含 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-it-up”,你可以使用 变压器收集方法阿帕奇共享区, ,例如:

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。

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

这是一个无需使用非 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 在这种情况下,特别是因为我们预先知道列表可能有多长。

@乔纳森:我可能会弄错,但我相信在这种情况下 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);

拉姆达吉 允许以非常简单且可读的方式做到这一点。例如,假设您有一个整数列表,并且想要将它们转换为相应的字符串表示形式,您可以编写类似的内容;

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 的仿通用容器只能存储对象,因此您的整数必须装箱为整数。原则上,它可以避免从 Object 到 Integer 的向下转换(因为它毫无意义,因为 Object 对于 String.valueOf 和 Object.toString 来说都足够好),但我不知道编译器是否足够聪明来做到这一点。从字符串到对象的转换或多或少应该是无操作的,所以我不想担心这个。

只是为了好玩,使用 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();

(免责声明:未编译。规格尚未最终确定。ETC。)

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

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

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

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

尽管我很喜欢 Jakarta 系列,但他们不支持 Generics 并且使用 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();
    }

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

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

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

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

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

与复制列表相比,这会更快并且占用更少的内存。

祝你好运!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top