Làm cách nào để chuyển đổi int [] thành Integer [] trong Java?


167

Tôi mới sử dụng Java và rất bối rối.

Tôi có một tập dữ liệu lớn có độ dài 4 int[]và tôi muốn đếm số lần mà mỗi kết hợp cụ thể của 4 số nguyên xảy ra. Điều này rất giống với việc đếm tần số từ trong tài liệu.

Tôi muốn tạo một Map<int[], double>ánh xạ mỗi int [] thành một số đếm đang chạy khi danh sách được lặp đi lặp lại, nhưng Map không có các kiểu nguyên thủy.

vì vậy tôi đã thực hiện Map<Integer[], Double>

dữ liệu của tôi được lưu trữ như một ArrayList<int[]>vòng lặp để vòng lặp của tôi phải giống như

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

Tôi không chắc chắn tôi cần mã nào ở phần bình luận để thực hiện công việc này để chuyển đổi int[]thành một Integer[]. Hoặc có lẽ tôi đang bối rối về cách đúng đắn để làm điều này.


6
"Tôi muốn tạo Bản đồ <int [], gấp đôi> ... nhưng Bản đồ không có các kiểu nguyên thủy." Như một trong những bài viết dưới đây đã chỉ ra, int [] không phải là kiểu nguyên thủy, vì vậy đó không phải là vấn đề thực sự. Vấn đề thực sự là các mảng không ghi đè .equals () để so sánh các phần tử. Theo nghĩa đó, chuyển đổi sang Integer [] (như tiêu đề của bạn nói) không giúp ích gì cho bạn. Trong đoạn mã trên, Hz.containsKey (q) vẫn không hoạt động như bạn mong đợi vì nó sử dụng .equals () để so sánh. Giải pháp thực sự là không sử dụng mảng ở đây.
newacct

Đừng muốn spam với một câu trả lời khác, nhưng đáng chú ý bây giờ là một ví dụ tài liệu về điều này.
Mureinik

Câu trả lời:


189

Bản địa Java 8 (một dòng)

Với Java 8, int[]có thể được chuyển đổi thành Integer[]dễ dàng:

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

Như những người khác đã nêu, Integer[]thường không phải là một khóa bản đồ tốt. Nhưng theo như chuyển đổi, bây giờ chúng ta có một mã gốc tương đối sạch sẽ.


3
Đó là cách chính xác. Nếu bạn cần Integer-Array như một danh sách bạn có thể viết:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
aw-think

để chuyển đổi thành một Integer[]tôi thực sự sẽ đề xuất sử dụng cú pháp sau: Integer[] boxed = IntStream.of(unboxed).boxed().toArray();Theo cách tương tự như @NwDx
YoYo

1
@JoD. Vâng, nó hoạt động. Nhưng dù sao cũng IntStream.ofgọi Arrays.stream. Tôi nghĩ rằng nó tùy thuộc vào sở thích cá nhân - tôi thích một chức năng được ghi đè hơn, một số tình yêu sử dụng lớp rõ ràng hơn.
Sheepy

2
Đó là một giải pháp điên rồ nhưng tuyệt vời! Cảm ơn bạn!
Ly khai

1
@VijayChavda Cú pháp mới, được gọi là tham chiếu phương thức , đã được giới thiệu vào năm 2014 với Java 8 như một phần của lambda ( JSR 335 Phần C ). Nó có nghĩa là the "new" method (constructor) of the Integer[] class.
Sheepy

79

Nếu bạn muốn chuyển đổi int[]thành một Integer[], không có cách nào tự động để làm điều đó trong JDK. Tuy nhiên, bạn có thể làm một cái gì đó như thế này:

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

Nếu bạn có quyền truy cập vào thư viện lang Apache , thì bạn có thể sử dụng ArrayUtils.toObject(int[])phương thức như thế này:

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

71
đó là một cách khó chịu để làm một vòng lặp for.
James Becwar

9
Đây là một điều hoàn toàn bình thường đối với mỗi ... Tôi không thấy phần khó chịu.
Dahaka

18
@Dahaka, sự khó chịu là trong việc sử dụng một trình vòng lặp valuetrong khi biến chỉ mục ilà có.
lcn

1
@Icn, tôi có thể thấy lý do tại sao một số người sẽ không thích phong cách đó, nhưng điều gì làm cho nó trở nên không mong muốn đến mức khó chịu?
Eddie

14
@icn, @Dahaka: Điều khó chịu là vì bạn đã sử dụng biến chỉ số tăng dần, nên cũng không cần phải sử dụng một biến cho mỗi; Mặc dù nó trông khá đẹp và đơn giản trong mã, đằng sau hậu trường liên quan đến chi phí không cần thiết. Một for (int i...)vòng lặp truyền thống sẽ hiệu quả hơn ở đây.
daiscog

8

Có lẽ bạn muốn khóa cho bản đồ khớp với giá trị của các phần tử thay vì danh tính của mảng. Trong trường hợp đó, bạn muốn một số loại đối tượng xác định equalshashCodenhư bạn mong đợi. Dễ nhất là chuyển đổi sang một List<Integer>, hoặc là ArrayListsử dụng tốt hơn Arrays.asList. Tốt hơn là bạn có thể giới thiệu một lớp đại diện cho dữ liệu (tương tự java.awt.Rectanglenhưng tôi khuyên bạn nên đặt các biến riêng tư cuối cùng và lớp cuối cùng cũng vậy).


Ồ, đây là một câu hỏi chuyển đổi mảng, theo cách khác: stackoverflow.com/questions/564392/iêu
Tom Hawtin - tackline

8

Sử dụng vòng lặp for thông thường mà không cần thư viện bên ngoài:

Chuyển đổi int [] thành 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
}

Chuyển đổi số nguyên [] thành 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

Tôi đã sai trong một câu trả lời trước đó. Giải pháp thích hợp là sử dụng lớp này làm khóa trong bản đồ bao bọc int [] thực tế.

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

và thay đổi mã của bạn như thế này:

   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
Tôi sẽ làm cho lớp cuối cùng, và cuối cùng trường tư. Tạo một bản sao phòng thủ của mảng trong hàm tạo (bản sao). Và chỉ trả về giá trị từ Arrays.equals chứ không phải là câu lệnh if đặc biệt đó. toString sẽ tốt đẹp.
Tom Hawtin - tackline

1
Oh và ném một NPE từ hàm tạo (có thể gọi bản sao) cho dữ liệu null và không có kiểm tra trong hashCode.
Tom Hawtin - tackline

Đúng .. Nhưng mã cho bằng, hashCode được tạo bởi IDEA :-). Nó hoạt động chính xác.
Mihai Toader

6
  1. Chuyển đổi int [] thành 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. Chuyển đổi số nguyên [] thành 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
Điều này là không chính xác do autoboxing. Trong ví dụ đầu tiên, bạn có thể làm một cách đơn giản newArray[i] = ids[i];và trong ví dụ thứ 2 newArray[i] = WrapperArray[i]:)
Eel Lee

3

Thay vì viết mã của riêng bạn, bạn có thể sử dụng IntBuffer để bọc int [] hiện có mà không phải sao chép dữ liệu vào mảng Integer

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

IntBuffer thực hiện so sánh để bạn có thể sử dụng mã bạn đã viết. Bản đồ chính thức so sánh các khóa sao cho a.equals (b) được sử dụng để nói hai khóa bằng nhau, vì vậy hai IntBuffers có mảng 1,2,3 - ngay cả khi các mảng nằm ở các vị trí bộ nhớ khác nhau - được cho là bằng nhau và vì vậy sẽ làm việc cho mã tần số của bạ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);
    }

}

Mong rằng sẽ giúp


2

Không chắc chắn lý do tại sao bạn cần một Double trong bản đồ của bạn. Xét về những gì bạn đang cố gắng thực hiện, bạn có một int [] và bạn chỉ muốn đếm số lần mỗi chuỗi xảy ra? Tại sao điều này lại cần một Double?

Những gì tôi sẽ làm là tạo một trình bao bọc cho mảng int với các phương thức .equals và .hashCode thích hợp để giải thích cho thực tế rằng chính đối tượng int [] không xem xét dữ liệu trong phiên bản của các phương thức này.

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

}

Và sau đó sử dụng multiset của google, nghĩa là chính xác cho mục đích đếm số lần xuất hiện, miễn là loại phần tử bạn đặt trong đó có các phương thức .equals và .hashCode thích hợp.

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

Sau đó, để có được số lượng cho bất kỳ sự kết hợp cụ thể nào:

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

Đây IntArrayWrapperchắc chắn là cách tiếp cận phù hợp để sử dụng một int[]mảng làm khóa băm, nhưng cần đề cập rằng một loại như vậy đã tồn tại . Bạn có thể sử dụng nó để bọc một mảng và không chỉ có nó hashCodeequalsthậm chí còn có thể so sánh được.
Holger

2

Cập nhật: Mặc dù các biên dịch dưới đây, nó ném một ArrayStoreExceptionlúc chạy. Quá tệ. Tôi sẽ để nó ở lại để tham khảo trong tương lai.


Chuyển đổi một int[], thành một Integer[]:

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

Tôi phải thừa nhận rằng tôi đã hơi ngạc nhiên khi biên dịch này, được đưa ra System.arraycopy là lowlevel và mọi thứ, nhưng nó có. Ít nhất là trong java7.

Bạn có thể chuyển đổi cách khác một cách dễ dàng.


2
Tôi không thấy nhiều giá trị trong việc giữ câu trả lời này "để tham khảo" khi nó không hoạt động. Tài liệu về System.arraycopy () thậm chí nói rằng nó sẽ không hoạt động cho mục đích này.
Zero3

2

Điều này làm việc như một nét duyên dáng!

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

Xin chào Tunaki, bạn có thể vui lòng khám phá đoạn mã trên cho tôi không? Khi tôi chạy qua trình gỡ lỗi, tôi thấy phương thức get và size được gọi tự động, tức là loại bỏ chúng được gọi một cách rõ ràng !! sao vậy?! bạn có thể giải thích dùm không?
forkdbloke

0

Chuyển đổi int [] thành 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

bạn không cần. int[]là một đối tượng và có thể được sử dụng làm chìa khóa bên trong bản đồ.

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

là định nghĩa đúng của bản đồ tần số.

Điều này đã sai :-). Các giải pháp thích hợp được đăng quá :-).


Rất cám ơn câu trả lời của bạn, tôi đã thử cái này trước và nó đã được biên dịch tốt, nhưng có vẻ như frequencies.containsKey(q)nó luôn luôn sai ngay cả khi tôi đã putcùng một mảng hai lần - có một số trục trặc ở đây liên quan đến định nghĩa của java với int []?

1
(Gợi ý, (new int [0]). Bằng (new int [0]) là sai; (new ArrayList <Integer> ()). Bằng (ArrayList mới <String> ()) là đúng.
Tom Hawtin - tackline

1
Ý tưởng tồi, khi so sánh mảng dựa trên sự bình đẳng tham chiếu . Đó là lý do Arrays.equals () tồn tại ...
sleske

Chỉ trích :-). Tôi đã hy vọng tôi đã đúng. Tuyên bố là đúng nhưng ngữ nghĩa là sai vì điều bình đẳng tham chiếu.
Mihai Toader

-3

Đơn giản chỉ cần sử dụng:

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.