Nasıl int [] için Java Integer [] dönüştürmek için?


167

Java'da yeniyim ve kafam çok karıştı.

4 uzunluğunda büyük bir veri setim var int[]ve 4 tamsayıdan oluşan her bir kombinasyonun kaç kez meydana geldiğini saymak istiyorum. Bu, bir belgedeki kelime sıklıklarını saymaya çok benzer.

Map<int[], double>Liste yinelendiği gibi her int [] çalışan bir sayıya eşleyen bir oluşturmak istiyorum , ancak Harita ilkel türleri almaz.

ben yaptım Map<Integer[], Double>

verilerim saklanır, ArrayList<int[]>böylece döngüm şöyle bir şey olmalı

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

Eminim bir dönüştürmek için bu işi yapmak için yorumun ne gerek kod değilim int[]bir etmek Integer[]. Ya da belki de bunu yapmanın doğru yolu hakkında kafam karıştı.


6
"Harita oluşturmak istiyorum <int [], double> ... ancak Harita ilkel türler almıyor." Aşağıdaki mesajlardan birinin işaret ettiği gibi, int [] ilkel bir tip değildir, bu yüzden asıl sorun bu değildir. Asıl sorun, dizilerin öğeleri karşılaştırmak için .equals () değerini geçersiz kılmamasıdır. Bu anlamda Tamsayı [] 'ya (başlığınızın dediği gibi) dönüştürmek size yardımcı olmaz. Yukarıdaki kodda, frequencies.containsKey (q), karşılaştırmak için .equals () kullandığından beklediğiniz gibi çalışmayacaktır. Gerçek çözüm burada dizileri kullanmamaktır.
newacct

Başka bir yanıtla spam göndermek istemiyorum, ancak şimdi bununla ilgili bir dokümantasyon örneği olduğunu belirtmek gerekir .
Mureinik

Yanıtlar:


189

Yerel Java 8 (bir satır)

Java 8 int[]ile Integer[]kolayca dönüştürülebilir :

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

Diğerlerinin belirttiği gibi Integer[], genellikle iyi bir harita anahtarı değildir. Ancak dönüşümle ilgili olarak, artık nispeten temiz ve yerel bir kodumuz var.


3
Bu arada doğru yol. Liste olarak Integer-Array'a ihtiyacınız varsa, şunları yazabilirsiniz:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
aw-think

dönüştürmek için Integer[]ben aslında aşağıdaki sözdizimini kullanarak öneririz: Integer[] boxed = IntStream.of(unboxed).boxed().toArray();@NwDx ile benzer şekilde
YoYo

1
@JoD. Evet, işe yarıyor. Ama yine de IntStream.ofçağırıyor Arrays.stream. Bence kişisel tercih aşağı iniyor - Ben geçersiz kılınmış bir işlevi tercih ediyorum, bazıları daha açık sınıf kullanarak seviyorum.
Sheepy

2
Bu çılgınca ama harika bir çözüm! Teşekkür ederim!
Rugal

1
@VijayChavda Yöntem başvuruları adı verilen yeni sözdizimi, 2014'te lambda'nın bir parçası olarak Java 8 ile tanıtıldı ( JSR 335 Kısım C ). Bu demektir the "new" method (constructor) of the Integer[] class.
Sheepy

79

Bir dönüştürmek istiyorsanız int[]bir etmek Integer[], JDK bunu yapmak için otomatik bir yol değildir yoktur. Ancak, böyle bir şey yapabilirsiniz:

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 dil kütüphanesine erişiminiz varsa , ArrayUtils.toObject(int[])yöntemi aşağıdaki gibi kullanabilirsiniz :

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

71
bu bir döngü için yapmak için kötü bir yol.
James Becwar

9
Bu her biri için son derece normal ... Kötü kısmı görmüyorum.
Dahaka

18
@Dahaka, sinirlilik valueindeksleme değişkeni varken bir yineleyici kullanıyor i.
LCN

1
@Icn, bazı insanların neden bu stili tercih etmediğini anlayabiliyorum, ama kötü olmayı bu kadar istenmeyen kılan nedir?
Eddie

14
@icn, @Dahaka: Nastiness, zaten artan bir indeks değişkeni kullandığınız için, her biri için de bir for kullanmaya gerek yoktur; kodda güzel ve basit görünse de, gereksiz ek yük içeren sahnelerin arkasında. Geleneksel bir for (int i...)döngü burada daha verimli olurdu.
daiscog

8

Büyük olasılıkla haritanın anahtarının, dizinin kimliği yerine öğelerin değeriyle eşleşmesini istiyorsunuz. Bu durumda, tanımlayacağınız equalsve hashCodebeklediğiniz gibi bir nesne istersiniz. En kolayı List<Integer>, ya bir ArrayListya da daha iyi bir kullanıma dönüştürmektir Arrays.asList. Bundan daha iyi, verileri temsil eden bir sınıf tanıtabilirsiniz (benzer java.awt.Rectangleancak değişkenleri özel final ve sınıf finali yapmayı tavsiye ederim).


Oh, işte bir dizi dönüştürme sorusu, tam
tersi

8

Harici kütüphaneler olmadan düzenli for-loop kullanma:

İnt [] öğesini Tamsayı [] birimine dönüştür:

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 [] birimini int [] birimine dönüştür:

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

Önceki bir cevapta yanılmışım. Uygun çözüm, bu sınıfı haritadaki gerçek int [] öğesini saran bir anahtar olarak kullanmaktır.

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

ve kodunuzu şu şekilde değiştirin:

   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
Sınıfı ve alanı özel final yapardım. Yapıcıdaki (klon) dizinin savunma kopyasını oluşturun. Ve değeri o tuhaf if ifadesine sahip olmak yerine Arrays.equals'tan döndürün. toString iyi olurdu.
Tom Hawtin - taktik

1
Oh ve boş veri için yapıcıdan (muhtemelen klon çağırıyor) bir NPE atmak ve hashCode check-in yok.
Tom Hawtin - tackline

Doğru .. Ama eşittir, hashCode kodu IDEA :-) tarafından üretilir. Doğru çalışıyor.
Mihai Toader,

6
  1. İnt [] öğesini Tamsayı [] birimine dönüştür

    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 [] birimini int [] birimine dönüştür

    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
Bu, otomatik boks nedeniyle oldukça yanlıştır. 1. örnekte basitçe newArray[i] = ids[i];ve 2. birinde yapabilirsiniz newArray[i] = WrapperArray[i]:)
Eel Lee

3

Kendi kodunuzu yazmak yerine, bir IntBuffer'ı kullanarak verileri bir Integer dizisine kopyalamak zorunda kalmadan mevcut int [] 'i sarmak için kullanabilirsiniz

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

IntBuffer, yazdığınız kodu kullanabilmeniz için karşılaştırılabilir bir uygulama gerçekleştirir. Resmi olarak haritalar anahtarları karşılaştırır, böylece a.equals (b) iki anahtarın eşit olduğunu söylemek için kullanılır, bu nedenle dizi 1,2,3'lü iki IntBuffer - diziler farklı bellek konumlarında olsa bile - eşit olduğu söylenir frekans kodunuz için çalışın.

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

}

umarım yardımcı olur


2

Haritanızda neden bir Double'e ihtiyacınız olduğundan emin değilim. Ne yapmaya çalıştığınız açısından, bir int [] var ve sadece her dizinin kaç kez meydana geldiğini saymak mı istiyorsunuz? Bu neden yine de bir Double gerektiriyordu?

Ne yapacağım int [] nesnesinin kendisi bu yöntemlerin sürümünde veri dikkate almaz gerçeğini açıklamak için uygun bir .equals ve .hashCode yöntemleri ile int dizi için bir sarıcı oluşturmaktır.

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

}

Ardından, içine koyduğunuz öğe türü uygun .equals ve .hashCode yöntemlerine sahip olduğu sürece, tam olarak gerçekleşen sayıları sayma amaçlı olan google guava'nın çoklu kümesini kullanın.

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

Ardından, belirli bir kombinasyon için sayımı almak için:

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

Bu IntArrayWrapperkesinlikle bir kullanımı için doğru yaklaşımdır int[]karma anahtar olarak diziyi, ancak böyle bir tip belirtmek gerekir ki zaten var Sen için kullanabilirsiniz ... bir dizi sarın ve sadece o vardır hashCodeve equalshatta karşılaştırılabilir.
Holger

2

Güncelleme: Her ne kadar aşağıda derlenmiş olsa da ArrayStoreException, çalışma zamanında atar . Çok kötü. Gelecekte referans olması için kalmasına izin vereceğim.


Bir int[], bir Integer[]:

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

İtiraf etmeliyim ki bu derlendiğine göre biraz şaşırdım System.arraycopy seviyeli ve her şey , ama öyle. En azından java7'de.

Diğer yolu da kolayca dönüştürebilirsiniz.


2
Bu cevabı işe yaramadığında "referans olarak" tutmakta çok değer göremiyorum. System.arraycopy () belgeleri bile bu amaç için çalışmayacağını belirtir.
Zero3

2

Bu bir cazibe gibi çalıştı!

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

Merhaba Tunaki, lütfen yukarıdaki kodu bana açıklar mısınız? Ben hata ayıklayıcı üzerinden çalıştırmak, ben get ve boyut yöntemi otomatik olarak çağrılır görüyorum, yani onları açıkça çağrılıyor ile! nasıl yani?! Açıklayabilir misin?
forkdbloke

0

İnt [] öğesini Tamsayı [] birimine dönüştür:

    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

ihtiyacın yok. int[]bir nesnedir ve haritanın içinde bir anahtar olarak kullanılabilir.

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

frekans haritasının doğru tanımıdır.

Bu yanlıştı :-). Uygun çözüm de gönderilir :-).


Cevabınız için çok teşekkürler Bu ilk denedim ve iyi derlenmiş, ama aynı diziyi iki kez frequencies.containsKey(q)olsa bile her zaman yanlış olurdu gibi görünüyor put- burada Java'nın int [] 'ile eşitlik tanımını içeren bir aksaklık var mı?

1
(İpucu, (yeni int [0]). Eşittir (yeni int [0]) yanlış; (yeni ArrayList <Integer> ()). Eşittir (yeni ArrayList <String> ()) doğrudur.
Tom Hawtin - tackline

1
Dizi karşılaştırması referans eşitliğine dayandığı için kötü fikir . Bu yüzden Arrays.equals () var ...
sleske

Lanet olsun :-). Haklı olduğumu umuyordum. Açıklama doğrudur, ancak referans eşitliği nedeniyle semantik yanlıştır.
Mihai Toader

-3

Basitçe kullanın:

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.