วิธีการแปลง int [] ถึง Integer [] ใน Java?


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
"ฉันต้องการสร้างแผนที่ <int [], double> ... แต่แผนที่ไม่ได้ใช้ประเภทดั้งเดิม" เนื่องจากหนึ่งในข้อความด้านล่างชี้ให้เห็น int [] ไม่ใช่ประเภทดั้งเดิมดังนั้นนั่นไม่ใช่ปัญหาจริง ปัญหาที่แท้จริงคืออาร์เรย์ไม่แทนที่. equals () เพื่อเปรียบเทียบองค์ประกอบ ในแง่นี้การแปลงเป็นจำนวนเต็ม [] (ตามที่ชื่อของคุณพูด) ไม่ช่วยคุณ ในรหัสข้างต้น frequencyencies.containKey (q) จะยังคงใช้งานไม่ได้ตามที่คุณคาดไว้เพราะใช้. equals () เพื่อเปรียบเทียบ ทางออกที่แท้จริงคือไม่ใช้อาร์เรย์ที่นี่
newacct

ไม่ต้องการสแปมด้วยคำตอบอื่น แต่น่าสังเกตว่าตอนนี้มีตัวอย่างเอกสารเกี่ยวกับเรื่องนี้
Mureinik

คำตอบ:


189

Native Java 8 (หนึ่งบรรทัด)

ด้วย 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อยู่ดี ฉันคิดว่ามันขึ้นอยู่กับความชอบส่วนตัว - ฉันชอบฟังก์ชั่นแทนที่หนึ่ง, ความรักโดยใช้คลาสที่ชัดเจนมากขึ้น
Sheepy

2
นั่นเป็นทางออกที่ยอดเยี่ยม แต่ยอดเยี่ยม! ขอบคุณ!
Rugal

1
@VijayChavda ไวยากรณ์ใหม่ที่เรียกว่าการอ้างอิงวิธีการได้รับการแนะนำในปี 2014 โดยมี Java 8 เป็นส่วนหนึ่งของแลมบ์ดา ( JSR 335 Part 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
นั่นเป็นวิธีที่น่ารังเกียจที่จะทำเพื่อห่วง
James Becwar

9
นี่เป็นเรื่องปกติสำหรับแต่ละคน ... ฉันไม่เห็นส่วนที่น่ารังเกียจ
Dahaka

18
@Dahaka ความน่ารังเกียจกำลังใช้ตัววนซ้ำvalueในขณะที่ตัวแปรการทำดัชนีiอยู่ที่นั่น
lcn

1
@ ฉันจะเห็นได้ว่าทำไมบางคนถึงไม่ชอบสไตล์นั้น แต่สิ่งที่ทำให้ไม่พึงปรารถนาเป็นสิ่งที่น่ารังเกียจ?
Eddie

14
@icn, @Dahaka: ความน่ารังเกียจก็คือเมื่อคุณใช้ตัวแปรดัชนีที่เพิ่มขึ้นแล้วคุณไม่จำเป็นต้องใช้ตัวแปรสำหรับแต่ละคนเช่นกัน ถึงแม้ว่ามันจะดูสวยและเรียบง่ายในรหัส แต่เบื้องหลังนั้นเกี่ยวข้องกับค่าใช้จ่ายที่ไม่จำเป็น การfor (int i...)วนซ้ำแบบดั้งเดิมจะมีประสิทธิภาพมากกว่าที่นี่
daiscog

8

สันนิษฐานว่าคุณต้องการให้กุญแจสำคัญในแผนที่จับคู่กับค่าขององค์ประกอบแทนที่จะเป็นตัวตนของอาร์เรย์ ในกรณีที่คุณต้องการวัตถุบางอย่างที่กำหนดequalsและhashCodeตามที่คุณคาด ง่ายที่สุดคือการแปลงเป็นList<Integer>, อย่างใดอย่างหนึ่งหรือการใช้งานที่ดีขึ้นArrayList Arrays.asListดีกว่าที่คุณสามารถแนะนำคลาสที่แสดงถึงข้อมูล (คล้ายกับjava.awt.Rectangleแต่ฉันขอแนะนำให้สร้างตัวแปรส่วนตัวสุดท้ายและคลาสสุดท้ายด้วย)


โอ้นี่เป็นคำถามการแปลงอาเรย์, วิธีอื่น ๆ : stackoverflow.com/questions/564392/…
Tom Hawtin - tackline

8

ใช้ for-loop ปกติโดยไม่ต้องใช้ไลบรารีภายนอก:

แปลง 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
}

แปลงจำนวนเต็ม [] เป็น 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
ฉันจะทำให้ชั้นเรียนสุดท้ายและภาคสนามส่วนตัวสุดท้าย ทำสำเนาการป้องกันของอาร์เรย์ในตัวสร้าง (โคลน) และเพียงแค่ส่งคืนค่าจาก Arrays.equals แทนที่จะมีลักษณะเฉพาะถ้ามีคำสั่ง toString จะดี
Tom Hawtin - tackline

1
โอ้และโยน NPE จากตัวสร้าง (อาจเรียกโคลน) สำหรับข้อมูลที่เป็นค่าว่างและไม่มีการเช็คอินใน hashCode
Tom Hawtin - tackline

จริง .. แต่รหัสสำหรับเท่ากับ hashCode ถูกสร้างโดย IDEA :-) มันทำงานได้อย่างถูกต้อง
Mihai Toader

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. แปลงจำนวนเต็ม [] เป็น 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
สิ่งนี้ค่อนข้างไม่ถูกต้องเนื่องจากการออโตบอท ในตัวอย่างที่ 1 คุณสามารถทำได้newArray[i] = ids[i];และในวันที่ 2 newArray[i] = WrapperArray[i]:)
Eel Lee

3

แทนที่จะเขียนรหัสของคุณเองคุณสามารถใช้ IntBuffer เพื่อตัด int ที่มีอยู่ [] โดยไม่ต้องคัดลอกข้อมูลลงในอาร์เรย์จำนวนเต็ม

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

IntBuffer ใช้การเปรียบเทียบเพื่อให้คุณสามารถใช้รหัสที่คุณเขียนไปแล้ว แผนที่อย่างเป็นทางการเปรียบเทียบคีย์ที่ใช้ a.equals (b) เพื่อบอกว่ามีสองปุ่มที่เท่ากันดังนั้น IntBuffers สองตัวที่มีอาร์เรย์ 1,2,3 - แม้ว่าอาร์เรย์จะอยู่ในตำแหน่งหน่วยความจำที่แตกต่างกัน - จะมีค่าเท่ากัน ทำงานสำหรับรหัสความถี่ของคุณ

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 [] และคุณแค่ต้องการนับว่าแต่ละครั้งเกิดขึ้นกี่ครั้ง? ทำไมต้องเป็น Double

สิ่งที่ฉันจะทำคือการสร้าง wrapper สำหรับ int array ด้วยวิธีการที่เหมาะสม. และวิธีการ. hashCode เพื่อพิจารณาข้อเท็จจริงว่าวัตถุ 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;
    }

}

และจากนั้นใช้ชุด multiset ของ Google guava ซึ่งมีความหมายตรงกับวัตถุประสงค์ในการนับจำนวนครั้งที่เกิดขึ้นตราบใดที่องค์ประกอบประเภทที่คุณใส่ไว้นั้นมีวิธีการ. และ. 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[]อาร์เรย์เป็นคีย์กัญชา แต่มันควรจะกล่าวว่าประเภทดังกล่าวมีอยู่แล้ว ... คุณสามารถใช้มันเพื่อห่ออาร์เรย์และไม่เพียง แต่มีมันhashCodeและequalsก็เปรียบได้แม้กระทั่ง
Holger

2

อัปเดต:แม้ว่าคอมไพล์ด้านล่างจะรวมเป็นArrayStoreExceptionat at runtime เลวร้ายเกินไป. ฉันจะปล่อยให้มันอยู่เพื่ออ้างอิงในอนาคต


การแปลง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

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 คุณช่วยอธิบายรหัสข้างต้นให้ฉันหน่อยได้ไหม? เมื่อฉันเรียกใช้ผ่านดีบักเกอร์ฉันจะเห็นวิธีการรับและขนาดที่ถูกเรียกโดยอัตโนมัติคือโดยไม่เรียกพวกเขาอย่างชัดเจน !! งั้นเหรอ?! คุณช่วยอธิบายได้ไหม
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มีอาร์เรย์เดิมสองครั้ง - มีข้อผิดพลาดบางประการเกี่ยวกับคำจำกัดความของความเท่าเทียมกับ int ของ java หรือไม่?

1
(คำแนะนำ, (int ใหม่ [0]). เท่ากับ (new int [0]) เป็นเท็จ; (ArrayList ใหม่ <Integer> ()). เท่ากับ (new ArrayList <String> ()) เป็นจริง
Tom Hawtin - tackline

1
แนวคิดที่ไม่ดีเนื่องจากการเปรียบเทียบอาร์เรย์ขึ้นอยู่กับความเท่าเทียมกันของการอ้างอิง นั่นเป็นเหตุผลที่ Arrays.equals () ที่อยู่ ...
sleske

ประณาม :-) ฉันหวังว่าฉันพูดถูก การประกาศนั้นถูกต้อง แต่ความหมายผิดเพราะสิ่งอ้างอิงที่เท่าเทียมกัน
Mihai Toader

-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.