如何在Java中将int []转换为Integer []?


167

我是Java新手,非常困惑。

我有一个长度为4的大型数据集,int[]我想计算4个整数的每个特定组合出现的次数。这与计算文档中的单词频率非常相似。

我想创建一个Map<int[], double>将每个int []映射到正在运行的计数的列表,但是列表不使用原始类型。

所以我做了 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不采用原始类型。” 正如下面的一篇文章指出的那样,int []不是原始类型,因此这不是真正的问题。真正的问题是数组不会重写.equals()来比较元素。从这种意义上讲,转换为Integer [](如您的标题所述)对您没有帮助。在上面的代码中,frequency.containsKey(q)仍然无法按预期工作,因为它使用.equals()进行比较。真正的解决方案是在这里不使用数组。
newacct

不想发送其他答案作为垃圾邮件,但值得注意的是,现在有一个有关此问题的文档示例
Mureinik '16

Answers:


189

本机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-think

要转换为Integer[]我居然会建议使用下面的语法:Integer[] boxed = IntStream.of(unboxed).boxed().toArray();在时装类似@NwDx
溜溜球

1
@JoD。是的,那行得通。但IntStream.of呼吁Arrays.stream反正。我认为这取决于个人喜好-我更喜欢一个重写的功能,有些喜欢使用更明确的类。
羊皮的

2
那是一个疯狂但很好的解决方案!谢谢!
2015年

1
@VijayChavda 2014年,Java 8作为lambda的一部分(JSR 335 Part C)引入了称为方法引用的新语法。这意味着。the "new" method (constructor) of the Integer[] class
羊皮的

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
这对于每个人来说都是完全正常的……我看不到令人讨厌的部分。
2012年

18
@Dahaka,最麻烦的是使用value索引变量i在那里的迭代器。
lcn

1
@Icn,我明白为什么有些人不喜欢这种风格,但是是什么使它如此讨厌以至于令人讨厌呢?
Eddie 2013年

14
@ icn,@ Dahaka:令人讨厌的是,由于您已经在使用递增的索引变量,因此也不需要使用for-each。尽管它在代码中看起来很漂亮而且很简单,但是在幕后却涉及不必要的开销。for (int i...)在这里,传统的循环会更有效。
daiscog 2015年

8

大概您希望映射的键匹配元素的值而不是数组的标识。在这种情况下,您需要某种可以定义equalshashCode符合您期望的对象。最简单的就是转换为List<Integer>,无论是一个ArrayList或更好地利用Arrays.asList。更好的是,您可以引入一个表示数据的类(类似于,java.awt.Rectangle但我建议将变量设置为final final,并将类也设置为final)。


哦,这里是一个数组转换的问题,只是周围的其他方法:stackoverflow.com/questions/564392/...
汤姆Hawtin - 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
我会让班级决赛,然后是田野赛场决赛。在构造函数中复制该数组的防御性副本(克隆)。只需从Arrays.equals返回值,而不要使用特殊的if语句。toString会很好。
汤姆·霍顿

1
哦,从构造函数中抛出一个NPE(可能调用clone)以获取空数据,并且不要将其签入hashCode。
Tom Hawtin-09年

是的..但是等号的代码,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];而在第二个示例中newArray[i] = WrapperArray[i]:)
Eel Lee,

3

无需编写自己的代码,您可以使用IntBuffer来包装现有的int [],而不必将数据复制到Integer数组中

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

IntBuffer实现了可比的功能,因此您可以使用已经编写的代码。正式地映射比较键,以便使用a.equals(b)表示两个键相等,因此,即使数组位于不同的内存位置,两个具有数组1,2,3的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 []并且只想计算每个序列发生多少次?为什么仍然需要Double?

我要做的是使用适当的.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;
    }

}

然后使用google guava的多重集(multiset),其确切目的是为了计算出现次数,只要您放入其中的元素类型具有适当的.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[]数组作为哈希键的正确方法,但是应该指出的是,这种类型已经存在 ……您可以使用它包装数组,不仅具有hashCodeequals,而且甚至具有可比性。
Holger

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两次相同的数组,它似乎也总是错误的-这里是否存在涉及java与int []相等的定义的故障?

1
。(提示,(新INT [0])等于(新INT [0])为假;(新的ArrayList <Integer>的())等于(新的ArrayList <字符串>())是真实的。
汤姆Hawtin - tackline

1
不好的主意,因为数组比较是基于引用相等性的。这就是为什么Arrays.equals()存在的原因
sleske

该死的 :-)。我希望我是对的。该声明是正确的,但是由于引用相等性的原因,语义是错误的。
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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.