List <Integer>からList <String>への変換


105

整数のリストがあり、List<Integer>すべての整数オブジェクトを文字列に変換して、新しいで仕上げたいと思いますList<String>

当然のことながら、新しい整数を作成List<String>してリストをループすることで新しいループを作成することもできましたString.valueOf()が、それを行うためのより良い(より自動化された)方法があるかどうか疑問に思っていましたか?

回答:


77

私の知る限り、これを行う唯一の方法は、反復してインスタンス化することです。次のようなもの(他の潜在的な助けのために、これを行う方法を知っていると確信しています):

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

シンプルな時、これを美と呼びます。
Elbek

1
元のポスターは、彼がこれを考えていたが、この解決策は複雑すぎるか退屈であると考えていたことを示しているようです。しかし、もっと簡単にできることを想像するのは難しいです。はい、時には、仕事を完了するために3行または4行のコードを記述する必要があります。
Jay

しかし、それによってArrayListにバインドされます。これは、元のリストと同じ実装を使用して実行できますか?
alianos- 2013

@Andreas oldList.getClass()。newInstance()が行います
Lluis Martinez

96

使用グアバ-プロジェクトからGoogleのコレクションを、あなたが使用できる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あるビューバッキングリストの-変換は、変換されたリストへの各アクセスに適用されます。

はnullに適用されるFunctions.toStringFunction()とをスローすることに注意してください。そのNullPointerExceptionため、リストにnullが含まれないことが確実な場合にのみ使用してください。


1
Functions.toStringFunction()の横にさらに準備ができた関数があればいいでしょう
ThiamTeck

1
クリーンですが、おそらくそれほど速くありません。値ごとに1つの追加の関数呼び出しですか?
h3xStream

3
HotSpotは関数呼び出しをインライン化できます。十分に呼び出されても、違いはありません。
Ben Lings、2010

3
これは実際に解決策であるため、私はこれに反対票を投じません。しかし、そのような単純なタスクを解決するためにライブラリの依存関係を追加するように人々を奨励することは、私にとっては行く必要はありません。
エスタニ2014

1
私たちのソリューションですでにGuavaを使用している場合の素晴らしいソリューション。
dudinha-dedalus

86

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

1
このtoString例では少し長くなっていますが、Guavaの関数ライブラリでサポートされていない変換では短くなります。カスタム関数はまだ簡単ですが、このJava 8ストリームよりもはるかに多くのコードです
lightswitch05

40

あなたがやっていることは結構ですが、あなたは「Javaにそれアップ」の必要性を感じる場合は使用することができ変圧器および収集方法からの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 2010

5
Apacheコレクションで新しい作業が行われていない限り、ジェネリックは実行されません。
KitsuneYMG 2010年

1
これは本当にJavaのようなものです。これは慣用的なJavaではなく、関数型プログラミングに似ています。Java 8でクロージャーを取得したときに、それを慣用的なJavaと呼ぶことができるでしょう。
ChristofferHammarström、2012年

あなたは間違いなく、ジェネリック医薬品の支援のためにそのためのCollections4(ない古い3.xのコレクション)を使用したい:commons.apache.org/proper/commons-collections/apidocs/org/...
JRA_TLL

"よりOOPまたは慣用的"になるように新しいクラスを定義する...これが単純なfor-eachループよりも優れていることはわかりません。それはより多くのコードを必要とし、機能を移動します(匿名クラスによって軽減される可能性がありますが、それでも)。この関数型スタイルは、関数型言語が数十年にわたって提供してきたように、適切な構文(つまり、Java 8以降のラムダ式)がある場合にのみ役立ちます。
TheOperator 2016年

9

String.valueOfのソースはこれを示しています。

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

それほど重要ではありませんが、toStringを使用します。


9

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

「勝利」の答えでトム・ホーティンが指摘したように、List <String>は単なるインターフェースであるため、インスタンス化することはできません。
Stu Thompson、

ええ、私はそれを知っていました。私はそれを試さずにコードを書いただけです。私の答えでそれを修正します。
ScArcher2 2008

9

以下は、JDK以外のライブラリで不正を行わないワンライナーソリューションです。

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));

7

GuavaとJava 8を使用した別のソリューション

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

3

コアJavaではなく、一般化されていませんが、人気のあるJakartaコモンズコレクションライブラリには、この種のタスクに役立つ抽象化がいくつかあります。具体的には、上の収集方法を見てください

CollectionUtils

プロジェクトで既にcommonsコレクションを使用している場合に考慮すべきこと。


4
Apacheコレクションを使用しないでください。それらは古く、時代遅れで、タイプセーフではなく、不十分に書かれています。
KitsuneYMG 2010年

3

jsightの答えで「ボクシング」について心配している人々には、何もありません。String.valueOf(Object)ここで使用され、へのボックス化解除intは実行されません。

使用するInteger.toString()か、String.valueOf(Object)可能なnullを処理する方法に依存するかどうか。例外をスローするか(おそらく)、リストに「null」の文字列を含めますか(たぶん)。前者の場合、NullPointerExceptionまたはその他のタイプをスローしますか?

また、jsightの応答の小さな欠点の1つListはインターフェースであり、それにnew演算子を使用できません。私はおそらくjava.util.ArrayListこの場合にa を使用するでしょう。特に、リストがどれくらいの長さであるかを前もって知っているからです。



2

@ジョナサン:私は間違っているかもしれませんが、この場合のString.valueOf()は、String.valueOf(int)にボックス化されるのではなく、String.valueOf(Object)関数を呼び出すと思います。String.valueOf(Object)は、nullの場合は「null」を返すか、null以外の場合はObject.toString()を呼び出します。これには、ボクシングは含まれません(ただし、新しい文字列オブジェクトのインスタンス化は明らかに含まれます)。


2

デバッグ以外の目的でObject.toString()を使用することは、この2つの機能が同等であるとしても(リストにnullがないと仮定して)、おそらく非常に悪い考えだと思います。標準ライブラリのクラスのtoString()メソッドを含め、開発者は警告なしにtoString()メソッドの動作を自由に変更できます。

ボックス化/ボックス化解除プロセスによって引き起こされるパフォーマンスの問題についても心配しないでください。パフォーマンスが重要な場合は、アレイを使用してください。それが本当に重要な場合は、Javaを使用しないでください。JVMの裏をかこうとすると、心が痛くなるだけです。


2

専門家のみの回答:

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

これは機能しますが、非効率が犠牲になります。Java文字列は1文字あたり2バイトなので、「、」は整数自体をカウントする前に、整数ごとに4バイトの固定コストを追加します。
Robert Christian

正規表現は、生のCPUサイクル効率の点でもっと問題があると思います。メモリに関しては、合理的な実装(の "Sun"の不合理な実装がからのString)と同じバッキング配列を共有するallため、実際には非常にメモリ効率が高く、長期的なパフォーマンスにとって重要です。あなただけのコースの要素の一つを維持したい場合を除き...
トムホーティン- tackline

2

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は、結果を反復している間のみ変換関数を適用します。


1

「ボクシングのオーバーヘッド」を回避することはできません。Javaの偽の汎用コンテナはオブジェクトのみを格納できるため、intはIntegerにボックス化する必要があります。原則的には、ObjectからIntegerへのダウンキャストを回避できます(ObjectはString.valueOfとObject.toStringの両方に十分対応できるため、無意味なので)。StringからObjectへの変換は多かれ少なかれ何もしないはずなので、私はそれについて心配するのを嫌がります。


コンパイラはそれを行うには十分スマートではありません。javacが実行されると、実際にはすべてのジェネリック型情報が取り除かれます。ジェネリックコレクションの基になる実装には、常にオブジェクト参照が格納されます。<T>パラメーター化を実際に省略して、「生の」タイプを取得できます。「List l = new List()」対「List <String> l = new List <String>()」。もちろん、これは「List <String> l =(List <String>)new List <Integer>()」が実際にコンパイルおよび実行されることを意味しますが、明らかに非常に危険です。
Dave Dopson、2011年

1

スペースの複雑さの原則に従っている解決策はありませんでした。整数のリストに多数の要素がある場合、それは大きな問題です。

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

1

ストリームの使用:結果が整数のリスト(List<Integer> result)であるとすると、次のようになります。

List<String> ids = (List<String>) result.stream().map(intNumber -> Integer.toString(intNumber)).collect(Collectors.toList());

それを解決する方法の1つ。お役に立てれば。


1

元のリストの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

ただ面白くするために、JDK7にあるはずのjsr166y fork-joinフレームワークを使用するソリューション。

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

これは基本的なことなので、外部ライブラリは使用しません(プロジェクトに依存関係が必要になる可能性があります)。

この種の仕事を行うために特別に作成された静的メソッドのクラスがあります。このためのコードは非常に単純なので、Hotspotに最適化を任せます。これは最近私のコードのテーマのようです:非常に単純な(まっすぐな)コードを書き、Hotspotにその魔法をさせてください。このようなコードに関してパフォーマンスの問題が発生することはほとんどありません-新しいVMバージョンが登場すると、速度のメリットなどすべてが得られます。

私がジャカルタコレクションを愛しているのと同じくらい、それらはGenericsをサポートせず、LCDとして1.4を使用しています。Googleコレクションはアルファサポートレベルとしてリストされているため、注意が必要です。


-1

私は問題に対するオブジェクト指向の解決策を取り入れたいと思っていました。

ドメインオブジェクトをモデル化する場合、ソリューションはドメインオブジェクト内にあります。ここでのドメインは、文字列値が必要な整数のリストです。

最も簡単な方法は、リストをまったく変換しないことです。

つまり、変換せずに変換するには、元の整数のリストを値のリストに変更します。値は次のようになります...

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

これは、リストをコピーするよりも速く、メモリ使用量も少なくなります。

幸運を!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.