I have a lot of two-dimensional integer arrays (size 8x8), which each have some numerical double value based on a calculation. I would like to store them in a data structure, so I would be able to look up a two-dimensional array and check what value I have given that array earlier.
I have been trying to use a hashCode of the two-dimensional arrays, that did not work.
I have also tried a hashMap with the array as key and I have tried to create custom objects as keys. But neither worked out for me, so I am doing something wrong. Where do I find the solution?
Since Java arrays do not override hashCode() and euqals() from Object native implementation they are not really suitable for lookups. For example two identical arrays are not equal:
int[][] a1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] a2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
System.out.println(a1.hashCode()); // 1277181601
System.out.println(a2.hashCode()); // 41903949
System.out.println(a1.equals(a2)); // false
One can however create a wrapper class that internally uses Arrays.deepHashCode() and Arrays.deepEquals() as follows:
public class IntIntArray {
private int[][] values;
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
IntIntArray that = (IntIntArray) o;
return Arrays.deepEquals(value, that.value);
}
#Override
public int hashCode() {
return Arrays.deepHashCode(value);
}
}
This class is suitable for value based lookups and can be used as Map key:
IntIntArray i1 = new IntIntArray(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
IntIntArray i2 = new IntIntArray(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
System.out.println(i1.hashCode()); // 30729379
System.out.println(i2.hashCode()); // 30729379
System.out.println(i1.equals(i2)); // true
If the you're using the SAME INSTANCE of the arrays, you can just use them as the key without doing anything:
#Test
public void test1() {
Integer[][] arr = new Integer[8][];
for (int i = 1; i <= 8; i++) {
arr[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
}
Map<Integer[][], Double> map = new HashMap<>();
map.put(arr, 5.7);
Double val = map.get(arr);
assert val == 5.7;
}
You can see here that getting the value from the map, using the same array that was used to put it, will return the wanted value.
This is because the implementation of the array of hash-code and equals is to check of the same instance, which is also good performance, if that is your case.
However, if you have different instances of the same array (key) it won't work:
#Test
public void test2() {
Integer[][] arr1 = new Integer[8][];
Integer[][] arr2 = new Integer[8][];
for (int i = 1; i <= 8; i++) {
arr1[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
arr2[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
}
Map<Integer[][], Double> map = new HashMap<>();
map.put(arr1, 5.7);
Double val = map.get(arr2);
assert val == null;
}
Instead, you'll need to create a "Key" object and implement equals and hash code for it:
class MyKey {
Integer[][] arr;
public MyKey(Integer[][] arr) {
this.arr = arr;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyKey myKey = (MyKey) o;
return Arrays.deepEquals(arr, myKey.arr);
}
#Override
public int hashCode() {
return Arrays.deepHashCode(arr);
}
}
and use it:
#Test
public void test2() {
Integer[][] arr1 = new Integer[8][];
Integer[][] arr2 = new Integer[8][];
for (int i = 1; i <= 8; i++) {
arr1[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
arr2[i-1] = new Integer[] {545*i,237*i,3513*i,461*i,465*i,20*i,134*i,352*i};
}
Map<MyKey, Double> map = new HashMap<>();
map.put(new MyKey(arr1), 5.7);
Double val = map.get(new MyKey(arr2));
assert val == 5.7;
}
Instead of using an array, use a List<List<Integer>> and use a map with hashCode as keys. As per the Java Documentation you should get the same value everytime if the values in the list are same. The hashCode is calculated by the following.
int hashCode = 1;
Iterator<E> i = list.iterator();
while (i.hasNext()) {
E obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
It also mentions that
This ensures that list1.equals(list2) implies that
list1.hashCode()==list2.hashCode() for any two lists, list1 and list2,
as required by the general contract of Object.hashCode().
Related
problem:https://leetcode.com/problems/maximum-units-on-a-truck/
I am supposed to sort array of arrays of size 2(eg. [[1,3],[2,2],[3,1]]) in descending order according to 2nd value of the inner element. i.e for 1st element[1,3]according to value 3. , but my code is resulting in error: no suitable method found for sort().Some Help would be appreciated.
here is my code in java
class Solution {
public int maximumUnits(int[][] boxTypes, int truckSize) {
Arrays.sort(boxTypes, new Comparator<int[][]>() {
public int compare(final int[][] entry1, final int[][] entry2) {
if (entry1[0][0] < entry2[0][0])
return 1;
else return -1;
}
}
);
for (int i = 0; i < boxTypes.length; i++)
System.out.println(boxTypes[i]);
return 0;
}
}
As mentioned in comments, you are sorting by inner element, which is int[], so you need Comparator<int[]>.
public class Solution {
public static void main(String[] args) {
int[][] input = new int[][]{new int[]{2, 2}, new int[]{1, 3}, new int[]{3, 1}};
Arrays.sort(input, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2) {
return Integer.compare(o2[1], o1[1]);
}
});
System.out.println(Arrays.deepToString(input));
}
}
Note return Integer.compare(o2[1], o1[1]);, second parameter is compared to first in order to achieve descending order.
You could also achieve same effect using lambda, to make it shorter and more readable.
public class Solution {
public static void main(String[] args) {
int[][] input = new int[][]{new int[]{2, 2}, new int[]{1, 3}, new int[]{3, 1}};
System.out.println("Initial array - " + Arrays.deepToString(input));
Arrays.sort(input, (o1, o2) -> Integer.compare(o2[1], o1[1]));
System.out.println("Sorted array - " + Arrays.deepToString(input));
}
}
First, you can't use native type in <>, you need to use Integer instead. Then what you need to compare is the inner array Integer[] if I'm not mistaken so your comparator can't work. Here you are just trying to sort 2 arrays of arrays based on the first element of the first array.
Here is what I would do (using stream):
Integer[][] sortedBoxTypes = Arrays.stream(boxTypes).sorted(Comparator.comparing(entry -> entry[1])).toArray(Integer[][]::new);
I have written a method to compare different 2D Arrays and output whether they are the same or not using .equals. In my main tester class I am comparing two 2D Integer arrays to each other which are the same so the output should be 'true' and then two 2D String arrays which are different so the output should be false. When testing different combinations, when I test equal and unequal Integer arrays I get the correct output. Testing different size arrays, correct output and testing equal string arrays I get the correct output.
The issue I am having is the fact that when I test two unequal String arrays the program returns true when they are unequal so the output should be false. Thanks in advance for any help or tips.
public boolean equals(Object[][] other) {
boolean isEqual = false;
if (myArray.length != other.length) {
return isEqual;
}
for (int i = 0; i < myArray.length; i++) {
for (int j = 0; j < myArray[i].length; j++) {
if (myArray[i][j].equals(other[i][j])) {
isEqual = true;
} else {
isEqual = false;
}
}
}
return isEqual;
}
Testing:
public class TwoDTester {
public static void main(String[] args) {
//Initializing arrays
Integer[][] firstArray = {{2, 3}, {3, 4}, {4, 5}};
Integer[][] secondArray = {{2, 3}, {3, 4}, {4, 5}};
//Creating TwoDArray object for comparisons
TwoDArray first = new TwoDArray(firstArray);
//Testing true or false
System.out.println(first.equals(secondArray));
//Initializing more arrays
String[][] thirdArray = {
{"Hello", "Goodbye"},
{"Hola", "Adios"},
{"Bonjour", "Au revoir"}};
String[][] fourthArray = {
{"Hello", "Goodbye"},
{"Ciao", "Addio"},
{"Bonjour", "Au revoir"}};
//Creating TwoDArray object for comparisons
TwoDArray third = new TwoDArray(thirdArray);
//Testing true or false
System.out.println(third.equals(fourthArray));
}
}
Since you require every corresponding element in the arrays to be equal, then you should simply quit the loops when finding something unequal. For example you can return false; in that case, while returning true only if the loops finish (which would mean all corresponding elements are equal).
With your current code, only the last element is taken into account (which will overwrite the isEqual with whatever result is the equality of the last two elements), while all previous values will not be taken into account.
Also, if you allow myArray to contain null elements, then consider using Objects.equals method to compare the objects for equality, but that's just a hint and not really related to the immediate problem.
As pointed out by #Jems, is should also be noted that in the following lines:
if (myArray.length != other.length)
{
return isEqual;
}
you are testing for equality only the number of rows each 2D array has. Note that you should also probably be comparing each row of each array for equality between their columns. For example something like:
if (myArray[i].length != other[i].length)
return false;
Not to mention the arrays being null themselves should be checked (that is both myArray, myArray[i], other and other[i]).
You can take the code of the Arrays.equals method and customize it so that it accepts 2D arrays:
public static void main(String[] args) {
Integer[][] one = {{1, 2}, {3, 4}, {5, 6}, null};
Integer[][] two = {{1, 2}, {3, 4}, {5, 6}, null};
String[][] three = {{"A", "B"}, {"C", "D"}, {"E", null}};
String[][] four = {{"A", "B"}, {"C", "D"}, {"E", null}};
System.out.println(equals2D(one, two)); // true
System.out.println(equals2D(three, four)); // true
}
/**
* The two 2D arrays are equal if they contain the same rows
* in the same order. Also, two array references are considered
* equal if both are 'null'.
*/
public static boolean equals2D(Object[][] a1, Object[][] a2) {
if (a1 == a2) return true;
if (a1 == null || a2 == null || a1.length != a2.length)
return false;
for (int i = 0; i < a1.length; i++)
if (!equals1D(a1[i], a2[i]))
return false;
return true;
}
/**
* The two rows are equal if they contain the same elements
* in the same order. Also, two row references are considered
* equal if both are 'null'.
*/
public static boolean equals1D(Object[] a1, Object[] a2) {
if (a1 == a2) return true;
if (a1 == null || a2 == null || a1.length != a2.length)
return false;
for (int i = 0; i < a1.length; i++)
if (!Objects.equals(a1[i], a2[i]))
return false;
return true;
}
I'm using matlabcontrol to control Matlab remotely with Java, is there a way to get a multidimensional numeric array out of the Object array returned to Java from the returningFeval method?
The returningFeval method returns an Object array and my Object[0] is a Matlab 2-D Array of doubles.
For example:
MatlabProxyFactory factory = new MatlabProxyFactory();
MatlabProxy proxy = factory.getProxy();
Object[] myData = proxy.returningFeval("myFunction", 2, "Arg");
double[][] a2DArray = myData[0];
This returns:
ClassCastException: "[D cannot be cast to [[D."
I know I can get the array using the MatlabTypeConverter class and the .getNumericArray method, but then I wouldn't be doing anything with the returned 'myData[0]'.
Any ideas?
Arrays.copyOf() method can be used to convert Object arrays into arrays of other types without ClassCastExceptions if they are really compatible.
Double[][] integerArray = Arrays.copyOf(a, a.length, Double[][].class);
http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#copyOf(U[],%20int,%20java.lang.Class)
Matlab uses one dimensional indexing and returns a double[d1*d2*...*dk] array. In order to convert this array to double[d1][d2]...[dk] the values of d1 ... dk should be known. The following code do the rest:
private static Object unflattenMatrix(boolean columnwise, double[] data, int... dimensions) {
Object res = Array.newInstance(double.class, dimensions);
List<Integer> dims = new LinkedList<>();
for (int i = 0; i < dimensions.length; i++) {
dims.add(dimensions[i]);
}
if (columnwise) {
Collections.reverse(dims);
}
setTraversingColumnwise(res, data, new LinkedList(), dims, columnwise);
return res;
}
static private int counter;
private static void setTraversingColumnwise(Object res, double[] data, List<Integer> indices, List<Integer> dimensions, boolean columnwise) {
if (indices.isEmpty()) {
counter = 0;
}
if (dimensions.isEmpty()) {
System.out.println(Arrays.toString(indices.toArray()));
setInDoubleArray(res, indices, data[counter++], columnwise);
} else {
int d = dimensions.remove(0);
for (int i = 0; i < d; i++) {
indices.add(i);
setTraversingColumnwise(res, data, indices, dimensions, columnwise);
indices.remove(indices.size() - 1);
}
dimensions.add(0,d);
}
}
private static void setInDoubleArray(Object doubleArr, List<Integer> indices, double data, boolean reverse) {
if (reverse) {
indices = new LinkedList<>(indices);
Collections.reverse(indices);
}
Object cur = doubleArr;
Iterator<Integer> iter = indices.iterator();
while (iter.hasNext()) {
int indx = iter.next();
if (iter.hasNext()) {
cur = ((Object[]) cur)[indx];
} else {
((double[]) cur)[indx] = data;
}
}
}
Sample usage :
double[][] res =(double[][]) unflattenMatrix(false,
new double[]{1, 2, 3, 4, 5, 6, 7, 8}, new int[]{2, 4});
The following Java code:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
gives the output
List contains y: false
which makes sense as x and y are references to different memory locations, however there is also a sense in which they are equal (they have the the same elements in the same order).
Is there a data structure which would return true to the query list.contains(y) in this example?
I don't believe there is a Java data structure that would return true for contains() as you have described.
The issue, as you probably know, is that for Java arrays, equals() only tests for Object identity and not "equality" as most would define it.
Since contains() relies on equals() in this case (and most of the time), you're stuck with the given behaviour.
You would have to implement a List that specifically overrode contains() to provide your desired behaviour for Java arrays, probably using Arrays.equals().
My suggestion is to instead use a List instead of an array; you'd then have a List<List<Integer>>. contains() should work in this scenario as it'll use equals() on the underyling List implementation.
You need to define a comparator for your arrays. Then when the list looks up the elements, it will use your comparator to see if they're the same:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>(new Comparator<int[]>() {
#Override
public int compare(int[] a1, int[] a2) {
if(a1 == a2) return 0;
if(a1 == null && a2 != null) return -1;
if(a1 != null && a2 == null) return 1;
if(a1.size() < a2.size()) return -1;
if(a1.size() > a2.size()) return 1;
for(int i = 0; i < a1.size(); i++) {
int comp = a1[i] - a2[i];
if(comp < 0) return -1;
if(comp > 0) return 1;
}
return 0;
}
});
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
It looks like you're really looking for a Set implementation.
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied
by its name, this interface models the mathematical set abstraction.
If you want to store sets of int values, you can use this Tuple class I wrote a while ago for another question on SO.
Set<Tuple> myTuples = new HashSet<Tuple>();
Tuple<Integer> x = Tuple.create(1, 2, 3);
Tuple<Integer> y = Tuple.create(1, 2, 3);
myTuples.add(x);
System.out.println("Set contains y: " + myTuples.contains(y)); // prints true
If order matters, you can use a SortedSet.
LinkedList uses equals to implement contains, so this should work:
public static void main(String args[]) {
static class Ints {
int[] array;
public Ints(int[] array) {
this.array = array;
}
public boolean equals(Object other) {
if (other instanceof Ints) {
return arraysEqual((Ints) other);
}
}
public boolean arraysEqual(Ints other) {
// check that this.array and other.array are same length and
// have same values. Do a null check somewhere too. :)
}
}
Ints x = new Ints(new int[] {1, 2, 3});
Ints y = new Ints(new int[] {1, 2, 3});
LinkedList<Ints> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
You would probably want to extend LinkedList into your own custom data structure and define a custom equality method if you wanted anything outside of the standard checking that is in place.
If you could use a Set instead of an array it might be easier. Have a look here or here
I have a large dataset of length 4 int[] and I want to count the number of times that each particular combination of 4 integers occurs. This is very similar to counting word frequencies in a document.
I want to create a Map<int[], double> that maps each int[] to a running count as the list is iterated over, but Map doesn't take primitive types.
So I made Map<Integer[], Double>.
My data is stored as an ArrayList<int[]>, so my loop should be something like:
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);
}
}
I'm not sure what code I need at the comment to make this work to convert an int[] to an Integer[]. Or maybe I'm fundamentally confused about the right way to do this.
Native Java 8 (one line)
With Java 8, int[] can be converted to Integer[] easily:
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() );
As others stated, Integer[] is usually not a good map key.
But as far as conversion goes, we now have a relatively clean and native code.
If you want to convert an int[] to an Integer[], there isn't an automated way to do it in the JDK. However, you can do something like this:
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);
}
If you have access to the Apache lang library, then you can use the ArrayUtils.toObject(int[]) method like this:
Integer[] newArray = ArrayUtils.toObject(oldArray);
Convert int[] to 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]);
Using regular for-loop without external libraries:
Convert int[] to 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
}
Convert Integer[] to 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
}
Presumably you want the key to the map to match on the value of the elements instead of the identity of the array. In that case you want some kind of object that defines equals and hashCode as you would expect. Easiest is to convert to a List<Integer>, either an ArrayList or better use Arrays.asList. Better than that you can introduce a class that represents the data (similar to java.awt.Rectangle but I recommend making the variables private final, and the class final too).
The proper solution is to use this class as a key in the map wrapping the actual 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;
}
}
And change your code like this:
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);
}
Convert int[] to 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;
}
Convert Integer[] to 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;
}
Rather than write your own code, you can use an IntBuffer to wrap the existing int[] without having to copy the data into an Integer array:
int[] a = {1, 2, 3, 4};
IntBuffer b = IntBuffer.wrap(a);
IntBuffer implements comparable, so you are able to use the code you already have written. Formally, maps compare keys such that a.equals(b) is used to say two keys are equal, so two IntBuffers with array 1,2,3 - even if the arrays are in different memory locations - are said to be equal and so will work for your frequency code.
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);
}
}
This worked like a charm!
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);
Though the below compiles, it throws a ArrayStoreException at runtime.
Converting an int[], to an Integer[]:
int[] old;
...
Integer[] arr = new Integer[old.length];
System.arraycopy(old, 0, arr, 0, old.length);
I must admit I was a bit surprised that this compiles, given System.arraycopy being lowlevel and everything, but it does. At least in Java 7.
You can convert the other way just as easily.
I am not sure why you need a Double in your map. In terms of what you're trying to do, you have an int[] and you just want counts of how many times each sequence occurs(?). Why would this require a Double anyway?
I would create a wrapper for the int array with a proper .equals and .hashCode methods to account for the fact that int[] object itself doesn't consider the data in its version of these methods.
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;
}
}
And then use Google Guava's multiset, which is meant exactly for the purpose of counting occurrences, as long as the element type you put in it has proper .equals and .hashCode methods.
List<int[]> list = ...;
HashMultiset<IntArrayWrapper> multiset = HashMultiset.create();
for (int values[] : list) {
multiset.add(new IntArrayWrapper(values));
}
Then, to get the count for any particular combination:
int cnt = multiset.count(new IntArrayWrapper(new int[] { 0, 1, 2, 3 }));
Int is a primitive. Primitives can’t accept null and have default value. Hence, to accept Null you need to use wrapper class Integer.
Option 1:
int[] nos = { 1, 2, 3, 4, 5 };
Integer[] nosWrapped = Arrays.stream(nos)
.boxed()
.toArray(Integer[]::new);
nosWrapped[5] = null // can store null
Option 2:
You can use any data structure that use wrapper class Integer
int[] nos = { 1, 2, 3, 4, 5 };
List<Integer> = Arrays.asList(nos)
You don't need it. int[] is an object and can be used as a key inside a map.
Map<int[], Double> frequencies = new HashMap<int[], Double>();
is the proper definition of the frequencies map.
This was wrong :-). The proper solution is posted too :-).