整数のリストがあり、List<Integer>
すべての整数オブジェクトを文字列に変換して、新しい。で終了したいと思いますList<String>
。
当然、新しい整数を作成して、各整数List<String>
を呼び出すリストをループすることもできますが、それを行うためのより良い(より自動化された)方法String.valueOf()
があるかどうか疑問に思いました。
整数のリストがあり、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));
}
あなたがしていることは問題ありませんが、「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);
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());
}
String.valueOf のソースはこれを示しています。
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
それほど重要ではありませんが、toString を使用します。
これは、JDK 以外のライブラリを使用しないワンライナー ソリューションです。
List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
コア Java ではなく、ジェネリック化されていませんが、人気のある Jakarta commons collections ライブラリには、この種のタスクに役立つ抽象化がいくつかあります。具体的には、上のcollectメソッドを見てください
プロジェクトで既にコモンズ コレクションを使用している場合は、考慮すべき事項があります。
jsight の回答で「ボクシング」について心配している人々へ: 何もありません。String.valueOf(Object)
がここで使用され、ボックス化解除int
は実行されません。
使用するかどうかはInteger.toString()
、String.valueOf(Object)
可能なヌルをどのように処理するかによって異なります。例外をスローするか (おそらく)、リストに「null」文字列を含めるか (おそらく)。NullPointerException
前者の場合、 aまたはその他のタイプをスローしますか?
また、jsight の応答には小さな欠陥が 1 つList
あります。これはインターフェイスであり、新しい演算子を使用することはできません。この場合はおそらく ajava.util.ArrayList
を使用します。特に、リストの長さがどれくらいになるかを事前に知っているからです。
@Jonathan:誤解される可能性がありますが、この場合のString.valueOf()は、String.valueOf(int)にボックス化されるのではなく、String.valueOf(Object)関数を呼び出すと思います。String.valueOf(Object)は、nullの場合は「null」を返すか、null以外の場合はObject.toString()を呼び出します。これには、ボクシングは含まれません(ただし、明らかに新しい文字列オブジェクトのインスタンス化が含まれます)。
デバッグ以外の目的で Object.toString() を使用することは、おそらく非常に悪い考えだと思いますが、この場合、2つは機能的に同等です(リストにnullがないと仮定します)。開発者は、標準ライブラリの任意のクラスの toString() メソッドを含め、警告なしに任意の toString() メソッドの動作を自由に変更できます。
ボックス化/ボックス化解除プロセスによって引き起こされるパフォーマンスの問題についても心配する必要はありません。パフォーマンスが重要な場合は、配列を使用してください。本当に重要な場合は、Java を使用しないでください。JVM の裏をかこうとしても、心痛につながるだけです。
Lambdajを使用すると、非常にシンプルで読みやすい方法でそれを行うことができます。たとえば、整数のリストがあり、それらを対応する文字列表現に変換したい場合、次のように書くことができます。
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 は、結果を反復しているときにのみ変換関数を適用します。
専門家のみの回答:
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 のフェイク ジェネリック コンテナーはオブジェクトしか格納できないため、int は Integers にボックス化する必要があります。原則として、Object から Integer へのダウンキャストを回避できます (Object は String.valueOf と Object.toString の両方に十分適しているため、無意味であるため) が、コンパイラがそれを行うのに十分スマートかどうかはわかりません。String から Object への変換は、多かれ少なかれノーオペレーションである必要があるため、そのことについて心配するのは気が進まないでしょう。
楽しみのために、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))
これは非常に基本的なことなので、外部ライブラリは使用しません (おそらく必要のない依存関係がプロジェクトに発生します)。
この種のジョブを実行するために特別に作成された静的メソッドのクラスがあります。このコードは非常に単純なので、Hotspot に最適化を任せます。これは、最近の私のコードのテーマのようです。非常に単純な (単純な) コードを記述し、Hotspot に魔法をかけてもらいます。このようなコードでパフォーマンスの問題が発生することはめったにありません。新しい VM バージョンが登場すると、すべての追加の速度の利点などを得ることができます。
Jakarta コレクションは大好きですが、Generics をサポートしておらず、LCD として 1.4 を使用しています。Google Collections はアルファ サポート レベルとしてリストされているため、注意が必要です。
空間の複雑さの原則に従う解決策は見当たりませんでした。整数のリストに多数の要素がある場合、それは大きな問題です。
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);
}
}
これは、リストをコピーするよりも高速で、使用するメモリも少なくなります。
幸運を!