Javaでint []をInteger []に変換する方法は?


167

私はJavaに不慣れで、非常に混乱しています。

長さ4の大きなデータセットがありint[]、4つの整数の特定の組み合わせが発生する回数を数えたい。これは、ドキュメント内の単語の出現頻度を数えるのとよく似ています。

Map<int[], double>リストが繰り返し処理されるときに各int []を現在のカウントにマップするを作成したいのですが、Mapはプリミティブ型を取りません。

だから私は作った Map<Integer[], Double>

私のデータはとして保存されているArrayList<int[]>ので、ループは次のようになります

ArrayList<int[]> data = ... // load a dataset`

Map<Integer[], Double> frequencies = new HashMap<Integer[], Double>();

for(int[] q : data) {

    // **DO SOMETHING TO convert q from int[] to Integer[] so I can put it in the map

    if(frequencies.containsKey(q)) {
    frequencies.put(q, tfs.get(q) + p);
    } else {
        frequencies.put(q, p);
    }
}

私は確かに私が変換するために、この作業を行うにコメントで必要なものをコードじゃありませんint[]Integer[]。または、これを行う正しい方法について根本的に混乱しています。


6
「Map <int []、double> ...を作成したいのですが、Mapはプリミティブ型を取りません。」以下の投稿の1つが指摘しているように、int []はプリミティブ型ではないため、それは本当の問題ではありません。実際の問題は、配列が.equals()をオーバーライドして要素を比較しないことです。その意味で、(タイトルが示すように)Integer []に変換しても役に立ちません。上記のコードでは、frequency.containsKey(q)は.equals()を使用して比較するため、期待どおりに機能しません。本当の解決策は、ここで配列を使用しないことです。
newacct 2009年

別の答えでスパムしたくないが、これに関するドキュメンテーションの例があることに注目する価値がある。
Mureinik '19

回答:


189

ネイティブJava 8(1行)

Java 8では、次のint[]ようにInteger[]簡単に変換できます。

int[] data = {1,2,3,4,5,6,7,8,9,10};

// To boxed array
Integer[] what = Arrays.stream( data ).boxed().toArray( Integer[]::new );
Integer[] ever = IntStream.of( data ).boxed().toArray( Integer[]::new );

// To boxed list
List<Integer> you  = Arrays.stream( data ).boxed().collect( Collectors.toList() );
List<Integer> like = IntStream.of( data ).boxed().collect( Collectors.toList() );

他の人が述べたように、Integer[]通常はは適切なマップキーではありません。しかし、変換に関しては、比較的クリーンでネイティブなコードができました。


3
その間、それは正しい方法です。あなたが書くことができ、リストとして整数・アレイが必要な場合:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
AW-考える

に変換するInteger[]には、実際には次の構文を使用することをお勧めします。Integer[] boxed = IntStream.of(unboxed).boxed().toArray();@ NwDxと同様の方法
YoYo

1
@JoD。はい、動作します。しかしとにかくIntStream.of呼び出しArrays.streamます。それは個人的な好みに帰着すると思います-私は1つのオーバーライドされた関数を好む、いくつかはより明示的なクラスを使用するのが好きです。
Sheepy

2
クレイジーですが素晴らしいソリューションです!ありがとうございました!
Rugal

1
@VijayChavda メソッド参照と呼ばれる新しい構文は、Java 8がラムダの一部として2014年に導入されました(JSR 335パートC)。という意味the "new" method (constructor) of the Integer[] classです。
Sheepy

79

変換したい場合int[]にはInteger[]、JDKでそれを行うための自動化された方法はありません。ただし、次のようなことができます。

int[] oldArray;

... // Here you would assign and fill oldArray

Integer[] newArray = new Integer[oldArray.length];
int i = 0;
for (int value : oldArray) {
    newArray[i++] = Integer.valueOf(value);
}

Apache langライブラリにアクセスできる場合は、次のArrayUtils.toObject(int[])ような方法を使用できます。

Integer[] newArray = ArrayUtils.toObject(oldArray);

71
これはforループを実行する厄介な方法です。
ジェームズベクワー

9
これは完全に正常なことです...嫌な部分は見当たりません。
ダハカ

18
@Dahaka、value索引変数iがそこにある間イスタレーターを使用するのがお洒落です。
lcn 2013

1
@Icn、なぜ一部の人々はそのスタイルを好まないのか理解できますが、それが嫌なほどに望ましくない理由は何ですか?
Eddie

14
@ icn、@ Dahaka:インスタレーションインデックス変数を既に使用しているため、for-eachを使用する必要がないというのがお洒落です。コードでは見た目もシンプルですが、不必要なオーバーヘッドを伴う舞台裏です。ここでは、従来のfor (int i...)ループの方が効率的です。
daiscog 2015年

8

おそらく、配列のIDではなく、要素の値でマップへのキーを一致させる必要があります。その場合、あなたは定義しequalshashCode期待どおりに必要です。最も簡単なのに変換することであるList<Integer>のいずれか、ArrayListまたはより良い使用Arrays.asList。それを超えると、データを表すクラスを導入できます(java.awt.Rectangle変数と同様ですが、変数をプライベートfinalにして、クラスもfinalにすることをお勧めします)。


:ああ、ここで配列変換質問、周りだけで、他の方法ですstackoverflow.com/questions/564392/...
トムホーティン- tackline

8

外部ライブラリなしで通常のforループを使用する:

int []をInteger []に変換します。

int[] primitiveArray = {1, 2, 3, 4, 5};
Integer[] objectArray = new Integer[primitiveArray.length];

for(int ctr = 0; ctr < primitiveArray.length; ctr++) {
    objectArray[ctr] = Integer.valueOf(primitiveArray[ctr]); // returns Integer value
}

Integer []をint []に変換します。

Integer[] objectArray = {1, 2, 3, 4, 5};
int[] primitiveArray = new int[objectArray.length];

for(int ctr = 0; ctr < objectArray.length; ctr++) {
    primitiveArray[ctr] = objectArray[ctr].intValue(); // returns int value
}

6

私は以前の答えで間違っていました。適切な解決策は、このクラスを実際のint []をラップするマップのキーとして使用することです。

public class IntArrayWrapper {
        int[] data;

        public IntArrayWrapper(int[] data) {
            this.data = data;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            IntArrayWrapper that = (IntArrayWrapper) o;

            if (!Arrays.equals(data, that.data)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            return data != null ? Arrays.hashCode(data) : 0;
        }
    }

次のようにコードを変更します。

   Map<IntArrayWrapper, Double > freqs = new HashMap<IntArrayWrapper, Double>();

    for (int[] data : datas) {
        IntArrayWrapper wrapper = new IntArrayWrapper(data);

        if ( freqs.containsKey(wrapper)) {
            freqs.put(wrapper, freqs.get(wrapper) + p);
        }

        freqs.put(wrapper, p);
    }

1
クラスはファイナルにし、フィールドはプライベートファイナルにします。コンストラクター(クローン)で配列の防御的コピーを作成します。そして、特異なifステートメントではなく、単にArrays.equalsから値を返します。toStringがいいでしょう。
トム・ホーティン-09年

1
ああ、nullデータのコンストラクター(おそらくcloneを呼び出す)からNPEをスローし、hashCodeにチェックを入れません。
トム・ホーティン-タックライン2009年

True ..しかし、equals、hashCodeのコードはIDEAによって生成されます:-)。正常に動作します。
Mihai Toader 2009年

6
  1. int []をInteger []に変換します

    public static Integer[] toConvertInteger(int[] ids) {
    
      Integer[] newArray = new Integer[ids.length];
         for (int i = 0; i < ids.length; i++) {
           newArray[i] = Integer.valueOf(ids[i]);
         }
       return newArray;
    }
  2. Integer []をint []に変換します

    public static int[] toint(Integer[] WrapperArray) {
    
       int[] newArray = new int[WrapperArray.length];
          for (int i = 0; i < WrapperArray.length; i++) {
             newArray[i] = WrapperArray[i].intValue();
          }
       return newArray;
    }

2
オートボクシングのため、これはかなり不正確です。第一の例では、あなたが簡単に行うことができますnewArray[i] = ids[i];し、2番目の1でnewArray[i] = WrapperArray[i]:)
うなぎリー

3

独自のコードを記述するのではなく、IntBufferを使用して、データをInteger配列にコピーせずに既存のint []をラップできます。

int[] a = {1,2,3,4};
IntBuffer b = IntBuffer.wrap(a);

IntBufferは、互換性を実装しているため、すでに記述したコードを使用できます。a.equals(b)を使用して2つのキーが等しいと正式にマップするキーを比較するため、配列が異なるメモリ位置にある場合でも、配列1,2,3の2つのIntBufferは等しいと見なされ、あなたの周波数コードのために働きます。

ArrayList<int[]> data = ... // load a dataset`

Map<IntBuffer, Double> frequencies = new HashMap<IntBuffer, Double>();

for(int[] a : data) {

    IntBuffer q = IntBuffer.wrap(a);

    if(frequencies.containsKey(q)) {
        frequencies.put(q, tfs.get(q) + p);
    } else {
        frequencies.put(q, p);
    }

}

それが役に立てば幸い


2

マップにDoubleが必要な理由がわかりません。あなたがやろうとしていることに関して、あなたはint []を持っていて、各シーケンスが何回発生したかをカウントしたいだけですか?とにかくこれにダブルが必要なのはなぜですか?

私がすることは、適切な.equalsおよび.hashCodeメソッドを使用してint配列のラッパーを作成し、int []オブジェクト自体がこれらのメソッドのバージョンのデータを考慮しないという事実を説明することです。

public class IntArrayWrapper {
    private int values[];

    public IntArrayWrapper(int[] values) {
        super();
        this.values = values;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(values);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        IntArrayWrapper other = (IntArrayWrapper) obj;
        if (!Arrays.equals(values, other.values))
            return false;
        return true;
    }

}

次に、グアバグアのマルチセットを使用します。これは、入力した要素タイプに適切な.equalsおよび.hashCodeメソッドが含まれている限り、出現回数を正確にカウントすることを目的としています。

List<int[]> list = ...;
HashMultiset<IntArrayWrapper> multiset = HashMultiset.create();
for (int values[] : list) {
    multiset.add(new IntArrayWrapper(values));
}

次に、特定の組み合わせの数を取得します。

int cnt = multiset.count(new IntArrayWrapper(new int[] { 0, 1, 2, 3 }));

これはIntArrayWrapper間違いなく使用するための適切なアプローチであるint[]ハッシュキーとして配列を、このようなA型がことに言及しなければならないすでに存在している ...あなたがするために使用することができ、配列をラップし、それを持っていないだけhashCodeequals、それも匹敵します。
Holger 2016

2

更新:以下はコンパイルさArrayStoreExceptionれますが、実行時にaがスローされます。残念な。今後の参考のために残しておきます。


変換int[]に、Integer[]

int[] old;
...
Integer[] arr = new Integer[old.length];
System.arraycopy(old, 0, arr, 0, old.length);

System.arraycopy低レベルとすべてのものを考えると、これがコンパイルされることに少し驚いたことを認めざるを得ませんが、実際はそうです。少なくともjava7では。

他の方法でも同じように簡単に変換できます。


2
この回答が機能しない場合に「参考用」にしておくことにはあまり価値がありません。System.arraycopy()のドキュメントには、この目的には使用できないと記載されています。
Zero3 2014

2

これは魅力のように働きました!

int[] mInt = new int[10];
Integer[] mInteger = new Integer[mInt.length];

List<Integer> wrapper = new AbstractList<Integer>() {
    @Override
    public int size() {
        return mInt.length;
    }

    @Override
    public Integer get(int i) {
        return mInt[i];
    }
};

wrapper.toArray(mInteger);

こんにちはTunakiです。上記のコードを説明してもらえますか?デバッガーを実行すると、getおよびsizeメソッドが自動的に呼び出されることがわかります。つまり、明示的に呼び出されていません!! どうして?!説明していただけますか?
forkdbloke

0

int []をInteger []に変換します。

    import java.util.Arrays;
    ...

    int[] aint = {1,2,3,4,5,6,7,8,9,10};
    Integer[] aInt = new Integer[aint.length];

    Arrays.setAll(aInt, i -> aint[i]);

-1

あなたは必要ありません。int[]オブジェクトであり、マップ内のキーとして使用できます。

Map<int[], Double> frequencies = new HashMap<int[], Double>();

周波数マップの適切な定義です。

これは間違っていました:-)。適切な解決策も掲載されています:-)。


私はこれを最初に試し、うまくコンパイルしfrequencies.containsKey(q)ましputたが、同じ配列を2回持っていても常にfalseになるようです-ここで、Javaのint []との同等性の定義に関連する問題がありますか?

1
(ヒント、(新しいINT [0])(新しいINT [0]を等しい)偽である;(新しいのArrayList <Integer型>())等号(新しいのArrayList <文字列>())が真である。。。
トムホーティン- tackline

1
配列の比較は参照の等価性に基づいているため、悪い考えです。そのため、Arrays.equals()が存在します...
sleske 2009年

くそー :-)。私が正しかったことを願っていました。宣言は正しいですが、参照の等価性のためにセマンティクスは間違っています。
Mihai Toader 2009年

-3

単に使用してください:

public static int[] intArrayToIntegerArray(int[] a) {
    Integer[] b = new Integer[a.length];
    for(int i = 0; i < array.length; i++){
        b[i] = a[i];
    }
    return g;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.