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

Converting List<Integer> to List<String>

提问人:ChrisThomas123 提问时间:8/21/2008 最后编辑:Joris SchellekensChrisThomas123 更新时间:8/7/2023 访问量:241231

问:

我有一个整数列表,我想将所有整数对象转换为字符串,从而以新的 .List<Integer>List<String>

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

Java 字符串 集合 整数

评论


答:

83赞 jsight 8/21/2008 #1

据我所知,迭代和实例化是唯一的方法。像这样的东西(对于其他人潜在的帮助,因为我相信你知道该怎么做):

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赞 Jay 9/8/2012
最初的发帖人似乎表明他已经想到了这一点,但认为这个解决方案过于复杂或乏味。但我很难想象还有什么比这更容易的。是的,有时您必须编写 3 或 4 行代码才能完成工作。
0赞 alianos- 4/10/2013
但这会将您绑定到 ArrayList。这可以使用与原始列表相同的实现来完成吗?
0赞 Lluis Martinez 5/10/2013
@Andreas oldList.getClass().newInstance() 就可以了
2赞 jsight 8/21/2008 #2

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

9赞 ScArcher2 8/21/2008 #3

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

评论

0赞 Stu Thompson 9/15/2008
正如 Tom Hawtin 在“获胜”答案中指出的那样,不能实例化 List<String>因为它只是一个接口。
0赞 ScArcher2 9/16/2008
呵呵,我知道。只是我没有尝试就写了代码。我会在我的答案中修复它。
2赞 Tim Frey 8/21/2008 #4

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

甚至不用担心装箱/拆箱过程引起的性能问题。如果性能至关重要,只需使用数组即可。如果它真的很关键,就不要使用 Java。试图智取JVM只会导致心痛。

9赞 Mike Polen 8/21/2008 #5

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

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

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

1赞 DrPizza 8/21/2008 #6

你无法避免“拳击开销”;Java 的仿泛型容器只能存储对象,因此必须将整数装箱到整数中。原则上,它可以避免从 Object 到 Integer 的下沉(因为它毫无意义,因为 Object 对 String.valueOf 和 Object.toString 都足够好),但我不知道编译器是否足够聪明来做到这一点。从 String 到 Object 的转换应该或多或少是空操作,所以我不愿意担心这个问题。

评论

0赞 Dave Dopson 6/5/2011
编译器不够聪明,无法做到这一点。当 javac 运行时,它实际上会去除所有泛型类型信息。泛型集合的基础实现始终存储对象引用。实际上,您可以省略 <T> 参数化并获得“原始”类型。“列表 l = new List()”与“List<String>l = new List<String>()”。当然,这意味着 “List<String> l = (List<String>)new List<Integer>()” 实际上会编译并运行,但显然非常危险。
3赞 serg10 8/21/2008 #7

不是核心 Java,也不是通用的,但流行的 Jakarta commons 集合库为此类任务提供了一些有用的抽象。具体来说,请看一下

产品组Utils

如果您已经在项目中使用共享资源集合,请考虑以下事项。

评论

4赞 KitsuneYMG 3/7/2010
切勿使用 Apache Collections。它们陈旧、过时、不安全且写得很差。
41赞 SCdF 8/21/2008 #8

你正在做的事情很好,但如果你觉得需要“Java-it-up”,你可以使用TransformerApache Commonscollect方法,例如:

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赞 Kannan Ekanath 2/17/2010
CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer());但是,StringValueTransformer 使用 String.valueOf ...
5赞 KitsuneYMG 3/7/2010
除非在 apache 集合上做了新的工作,否则他们不会做泛型。
1赞 Christoffer Hammarström 1/8/2012
这真的是 Java-ing-it 下来了。这不是惯用的 Java,更像是函数式编程。也许当我们在 Java 8 中获得闭包时,你能称它为惯用的 Java 吗?
0赞 JRA_TLL 1/6/2016
您肯定希望使用 Collections4(而不是旧的 3.x Collections)来支持泛型:commons.apache.org/proper/commons-collections/apidocs/org/...
0赞 TheOperator 2/1/2016
定义一个新类只是为了“更OOP或惯用”......我看不出这比简单的 for-each 循环更好。它需要更多的代码并将功能移开(这可以通过匿名类来缓解,但仍然如此)。这种函数式风格只有在有像样的语法(即 Java 8 以来的 lambda 表达式)时才开始变得有用,就像函数式语言几十年来一直提供的那样。
4赞 erickson 8/29/2008 #9

对于jsight中关心“拳击”的人的回答:没有。 在此处使用,并且从未执行过拆箱操作。String.valueOf(Object)int

是否使用 或 取决于要如何处理可能的 null。您是想抛出异常(可能),还是列表中有“null”字符串(可能)。如果是前者,你想扔一个还是其他类型?Integer.toString()String.valueOf(Object)NullPointerException

另外,jsight 的响应中有一个小缺陷:是一个接口,你不能在上面使用 new 运算符。在这种情况下,我可能会使用 a,特别是因为我们预先知道列表可能有多长。Listjava.util.ArrayList

2赞 Tom Hawtin - tackline 9/12/2008 #10

仅供专家回答:

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

评论

0赞 Robert Christian 10/14/2010
这是可行的,但代价是效率低下。Java 字符串是每个字符两个字节,因此 “, ” 在计算整数本身之前为每个整数增加了四个字节的固定成本。除其他外。
0赞 Tom Hawtin - tackline 10/14/2010
我认为正则表达式在原始 CPU 周期效率方面可能是一个更大的问题。在内存方面,我猜一个合理的实现(假设“Sun”不合理的实现)将共享相同的后备数组(从 ),所以实际上会非常节省内存,这对于长期性能很重要。当然,除非你只想保留其中一个元素......Stringall
0赞 Tom Hawtin - tackline 9/15/2008 #11

只是为了好玩,一个使用 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))
0赞 John Wright 9/24/2008 #12

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

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

尽管我非常喜欢 Jakarta 系列,但它们不支持泛型并使用 1.4 作为 LCD。我对 Google Collections 持谨慎态度,因为它们被列为 Alpha 支持级别!

107赞 Ben Lings 8/4/2009 #13

使用 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 是后备列表上的视图 - 转换将应用于对转换列表的每次访问。Listtransform

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

评论

1赞 ThiamTeck 9/7/2010
如果除了 Functions.toStringFunction() 之外还有更多现成的函数,那就太好了
1赞 h3xStream 12/9/2010
干净,但可能没有那么快。每个值 1 个额外的函数调用?
3赞 Ben Lings 12/10/2010
HotSpot 可以内联函数调用 - 所以如果它被调用得足够多,它应该不会有什么不同。
4赞 estani 3/1/2014
我不对此投反对票,因为它确实是一个解决方案。但是鼓励人们添加库依赖项来解决如此简单的任务对我来说是行不通的。
1赞 JRA_TLL 1/6/2016
这样做的一个潜在问题是,转换是延迟应用的(可能多次)。为了避免这种情况,您可能希望返回,new ArrayList<>(Lists.transform(integers, Functions.toStringFunction()))
2赞 Mario Fusco 3/7/2010 #14

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

9赞 Garrett Hall 4/26/2011 #15

这是一个单行解决方案,不会使用非 JDK 库作弊。

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
-1赞 Rodney P. Barbati 9/8/2012 #16

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

如果对域对象进行建模,则解决方案位于域对象中。这里的域是我们需要字符串值的整数列表。

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

话虽如此,为了在不转换的情况下进行转换,请将原始的 Integer 列表更改为 List of Value,其中 Value 如下所示......

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

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

107赞 Hakanai 4/12/2014 #17

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

评论

1赞 lightswitch05 10/25/2017
虽然这个例子有点长,但对于Guava的函数库不支持的转换来说,它最终会更短。自定义函数仍然很简单,但它的代码比这个 Java 8 流要多得多toString
1赞 granadaCoder 10/17/2020
对于未来的读者来说,这也是“反向”的方式。谢谢trejkaz!Collection<String> keys = 等等等等;集合<整数> keyInts = keys.stream().map(Integer::p arseInt).collect(Collectors.toList());
7赞 sandrozbinden 4/25/2014 #18

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

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));
0赞 nagendra547 8/30/2017 #19

我没有看到任何遵循空间原理的解决方案 复杂性。如果整数列表包含大量元素,则它是 大问题。

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();
    }
4赞 Mahesh Yadav 6/19/2019 #20
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())

评论

0赞 Adnan 10/1/2020
@RequiresApi(api = Build.VERSION_CODES.N)
0赞 Kathir 8/31/2021
@Adnan您可能指的是 Android 的使用。OP一般都在问。所以,Java 8+ 应该就足够了
3赞 Solubris 4/16/2020 #21

使用原始列表上的 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)));
0赞 Oleksandr Pyrohov 8/7/2023 #22

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

以防万一,对于那些使用 >= 16 版本的 Java 的幸运儿来说,不再需要冗长的调用链,只需使用 Stream 接口 toList 中的新方法即可:.collect(Collectors.toList())

List<String> strings = integers.stream().map(String::valueOf).toList();

所以,现在它甚至比番石榴版本还要短:)