Bagaimana cara mengubah int [] ke Integer [] di Java?

167

Saya baru ke Jawa dan sangat bingung.

Saya memiliki dataset besar dengan panjang 4 int[]dan saya ingin menghitung berapa kali setiap kombinasi 4 bilangan bulat terjadi. Ini sangat mirip dengan menghitung frekuensi kata dalam dokumen.

Saya ingin membuat Map<int[], double>yang memetakan setiap int [] ke jumlah yang sedang berjalan karena daftar diulangi, tetapi Peta tidak menggunakan tipe primitif.

jadi saya membuat Map<Integer[], Double>

data saya disimpan ArrayList<int[]>jadi loop saya harus seperti ini

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

Saya tidak yakin kode apa yang saya butuhkan di komentar untuk membuat pekerjaan ini untuk mengkonversi int[]menjadi Integer[]. Atau mungkin saya pada dasarnya bingung tentang cara yang tepat untuk melakukan ini.

Jonik
sumber
6
"Saya ingin membuat Peta <int [], gandakan> ... tetapi Peta tidak menggunakan tipe primitif." Seperti yang ditunjukkan oleh salah satu tulisan di bawah, int [] bukan tipe primitif, jadi itu bukan masalah sebenarnya. Masalah sebenarnya adalah array tidak menimpa .equals () untuk membandingkan elemen. Dalam hal itu, konversi ke Integer [] (seperti judul Anda katakan) tidak membantu Anda. Dalam kode di atas, frequency.containsKey (q) masih tidak akan berfungsi seperti yang Anda harapkan karena menggunakan .equals () untuk membandingkan. Solusi sebenarnya adalah tidak menggunakan array di sini.
newacct
Tidak ingin mengirim spam dengan jawaban lain, tetapi patut dicatat sekarang ada contoh dokumentasi tentang ini.
Mureinik

Jawaban:

189

Native Java 8 (satu baris)

Dengan Java 8, int[]dapat dikonversi dengan Integer[]mudah:

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

Seperti yang dinyatakan orang lain, Integer[]biasanya bukan kunci peta yang baik. Namun sejauh konversi berjalan, kami sekarang memiliki kode asli dan relatif bersih.

Domba
sumber
3
Sementara itu cara yang benar. Jika Anda memerlukan Integer-Array sebagai daftar, Anda dapat menulis:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
aw-think
untuk mengkonversi ke Integer[]saya benar-benar menyarankan menggunakan sintaks berikut: Integer[] boxed = IntStream.of(unboxed).boxed().toArray();Dengan cara yang sama seperti @NwDx
YoYo
1
@ Jo. Ya, itu berhasil. Tapi tetap saja IntStream.ofmenelepon Arrays.stream. Saya pikir itu turun ke preferensi pribadi - Saya lebih suka satu fungsi yang ditimpa, beberapa suka menggunakan kelas yang lebih eksplisit.
Sheepy
2
Itu solusi gila tapi hebat! Terima kasih!
Rugal
1
@ VijayChavda Sintaks baru, disebut referensi metode , diperkenalkan pada tahun 2014 dengan Java 8 sebagai bagian dari lambda ( JSR 335 Bagian C ). Artinya the "new" method (constructor) of the Integer[] class.
Sheepy
79

Jika Anda ingin mengonversikan int[]ke Integer[], tidak ada cara otomatis untuk melakukannya di JDK. Namun, Anda dapat melakukan sesuatu seperti ini:

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

Jika Anda memiliki akses ke perpustakaan lang Apache , maka Anda dapat menggunakan ArrayUtils.toObject(int[])metode seperti ini:

Integer[] newArray = ArrayUtils.toObject(oldArray);
Eddie
sumber
71
Itu cara jahat untuk melakukan for loop.
James Becwar
9
Ini adalah hal yang normal untuk setiap ... Saya tidak melihat bagian yang jahat.
Dahaka
18
@ Wahaka, nastiness dalam menggunakan iterator valuesementara variabel pengindeksan iada.
lcn
1
@Icn, saya bisa melihat mengapa beberapa orang tidak suka gaya itu, tapi apa yang membuatnya sangat tidak diinginkan sehingga menjadi jahat?
Eddie
14
@icn, @Dahaka: Nastiness adalah bahwa karena Anda sudah menggunakan variabel indeks tambahan, tidak perlu menggunakan masing-masing juga; meskipun terlihat cantik dan sederhana dalam kode, di belakang layar itu melibatkan overhead yang tidak perlu. for (int i...)Perulangan tradisional akan lebih efisien di sini.
daiscog
8

Agaknya Anda ingin kunci peta cocok dengan nilai elemen, bukan identitas array. Dalam hal ini Anda menginginkan semacam objek yang mendefinisikan equalsdan hashCodeseperti yang Anda harapkan. Cara termudah adalah mengonversi menjadi List<Integer>, baik ArrayListpenggunaan atau lebih baik Arrays.asList. Lebih baik dari itu Anda bisa memperkenalkan kelas yang mewakili data (mirip dengan java.awt.Rectangletetapi saya sarankan membuat variabel pribadi akhir, dan kelas juga final).

Tom Hawtin - tackline
sumber
Oh, inilah pertanyaan konversi larik, hanya sebaliknya: stackoverflow.com/questions/564392/…
Tom Hawtin - tackline
8

Menggunakan for-loop reguler tanpa perpustakaan eksternal:

Konversi int [] ke 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
}

Konversikan Integer [] ke 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
}
perak
sumber
6

Saya salah dalam jawaban sebelumnya. Solusi yang tepat adalah dengan menggunakan kelas ini sebagai kunci dalam peta yang membungkus int aktual [].

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

dan ubah kode Anda seperti ini:

   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);
    }
Mihai Toader
sumber
1
Saya akan membuat kelas final, dan lapangan pribadi final. Buat salinan defensif array di konstruktor (klon). Dan kembalikan nilai dari Array. Sama dengan daripada memiliki pernyataan if khusus. toString akan menyenangkan.
Tom Hawtin - tackline
1
Oh dan melempar NPE dari konstruktor (mungkin memanggil klon) untuk data nol, dan tidak memiliki kode hash check in.
Tom Hawtin - tackline
Benar .. Tapi kode untuk equals, kode hash dihasilkan oleh IDEA :-). Itu bekerja dengan benar.
Mihai Toader
6
  1. Konversi int [] ke 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. Konversi Integer [] ke 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;
    }
Keras
sumber
2
Ini agak tidak akurat karena autoboxing. Dalam contoh 1, Anda cukup melakukannya newArray[i] = ids[i];dan pada yang kedua newArray[i] = WrapperArray[i]:)
Eel Lee
3

Daripada menulis kode Anda sendiri, Anda dapat menggunakan IntBuffer untuk membungkus int [] yang ada tanpa harus menyalin data ke dalam array Integer

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

IntBuffer mengimplementasikan sebanding sehingga Anda dapat menggunakan kode yang sudah Anda tulis. Peta secara formal membandingkan kunci sehingga a.equals (b) digunakan untuk mengatakan dua kunci sama, sehingga dua IntBuffers dengan array 1,2,3 - bahkan jika array berada di lokasi memori yang berbeda - dikatakan sama dan akan bekerja untuk kode frekuensi Anda.

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

}

Semoga itu bisa membantu

Chris
sumber
2

Tidak yakin mengapa Anda membutuhkan Dobel di peta Anda. Dalam hal apa yang Anda coba lakukan, Anda memiliki int [] dan Anda hanya ingin menghitung berapa kali setiap urutan terjadi? Mengapa ini membutuhkan Double?

Apa yang akan saya lakukan adalah membuat pembungkus untuk array int dengan .equals dan .hashCode metode yang tepat untuk menjelaskan fakta bahwa objek int [] itu sendiri tidak mempertimbangkan data dalam versi metode ini.

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

}

Dan kemudian gunakan multiset google jambu, yang dimaksudkan tepat untuk tujuan penghitungan kejadian, selama jenis elemen yang Anda masukkan di dalamnya memiliki metode .eash dan .hashCode yang tepat.

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

Lalu, untuk mendapatkan hitungan untuk kombinasi tertentu:

int cnt = multiset.count(new IntArrayWrapper(new int[] { 0, 1, 2, 3 }));
Mat
sumber
Ini IntArrayWrapperjelas merupakan pendekatan yang tepat untuk menggunakan int[]array sebagai kunci hash, tetapi harus disebutkan bahwa tipe seperti itu sudah ada ... Anda dapat menggunakannya untuk membungkus array dan tidak hanya memilikinya hashCodedan equals, bahkan sebanding.
Holger
2

Pembaruan: Meskipun kompilasi di bawah ini, ia melempar ArrayStoreExceptionpada saat runtime. Sangat buruk. Saya akan membiarkannya untuk referensi di masa mendatang.


Mengubah sebuah int[], menjadi Integer[]:

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

Saya harus mengakui bahwa saya sedikit terkejut bahwa ini dikompilasi, diberikan System.arraycopy tingkat rendah dan segalanya, tetapi ternyata demikian. Setidaknya dalam java7.

Anda dapat mengonversi cara lain dengan mudah.

Thomas Ahle
sumber
2
Saya tidak melihat banyak manfaat dalam menjaga jawaban ini "untuk referensi" ketika tidak berhasil. Dokumentasi untuk System.arraycopy () bahkan menyatakan bahwa itu tidak akan berfungsi untuk tujuan ini.
Zero3
2

Ini bekerja seperti pesona!

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);
Itamar Borges
sumber
Hai Tunaki, bisakah Anda menjelaskan kode di atas untuk saya? ketika saya jalankan melalui debugger, saya melihat metode get dan size dipanggil secara otomatis, yaitu tanpa memanggil mereka secara eksplisit !! bagaimana?! bisakah kamu menjelaskan?
forkdbloke
0

Konversi int [] ke 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]);
zemiak
sumber
-1

kamu tidak perlu int[]adalah objek dan dapat digunakan sebagai kunci di dalam peta.

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

adalah definisi yang tepat dari peta frekuensi.

Ini salah :-). Solusi yang tepat diposting juga :-).

Mihai Toader
sumber
Terima kasih banyak atas balasan Anda, saya sudah mencoba ini dulu dan sudah dikompilasi dengan baik, tetapi sepertinya frequencies.containsKey(q)akan selalu salah bahkan jika saya putmemiliki array yang sama dua kali - apakah ada kesalahan di sini yang melibatkan definisi java tentang persamaan dengan int []?
1
(Petunjuk, (int baru [0]). Equals (int baru [0]) salah; (ArrayList baru <Integer> ()) sama dengan (ArrayList <String> ()) baru benar.
Tom Hawtin - tackline
1
Gagasan buruk, karena perbandingan array didasarkan pada kesetaraan referensi . Itu sebabnya Arrays.equals () ada ...
sleske
Sial :-). Saya berharap saya benar. Deklarasi itu benar tetapi semantiknya salah karena referensi kesetaraan hal.
Mihai Toader
-3

Cukup gunakan:

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;
}
Lurzapps
sumber