How can I maintain an ArrayList
of unique arrays?
For instance, if I have the following arrays:
int [] a = {1,2,3};
int [] b = {2,1,3};
int [] c = {2,1,3};
According to my logic I am considering unique combinations. So in the case above a = b = c
because they all contain "1"
, "2"
, "3"
.
Ideally I am wondering if there is a data structure in Java that recognizes this.
I tried the following:
Set<int []> result = new LinkedHashSet<>();
int [] x = {1,2,3};
int [] z = {2,1,3};
int [] m = {2,1,3};
result.add(x);
result.add(z);
result.add(m);
for(int [] arr: result){
printArray(arr);
}
My output was:
1 2 3
2 1 3
2 1 3
Ideally I would want my output to only print one of the combinations above.
ArrayList maintains the insertion order i.e order of the object in which they are inserted. HashSet is an unordered collection and doesn't maintain any order. ArrayList allows duplicate values in its collection. On other hand duplicate elements are not allowed in Hashset.
You can create a method to add if not equals like so :
public static Set<int[]> addIfNotExist(Set<int[]> result, int[] array) {
Arrays.sort(array);
boolean check = result.stream()
.anyMatch(a -> {
Arrays.sort(a);
return Arrays.equals(a, array);
});
if (check) {
return result;
} else {
result.add(array);
return result;
}
}
Then you can call your method like so :
result = addIfNotExist(result, x);
result = addIfNotExist(result, z);
result = addIfNotExist(result, m);
Output
[1, 2, 3]
Or if you use a static Set
, you can just use :
static Set<int[]> result = new LinkedHashSet<>();
public static void main(String[] args) {
int[] x = {1, 2, 3};
int[] z = {2, 1, 3};
int[] m = {2, 1, 3};
addIfNotExist(result, x);
addIfNotExist(result, z);
addIfNotExist(result, m);
for (int[] arr : result) {
System.out.println(Arrays.toString(arr));
}
}
public static void addIfNotExist(Set<int[]> result, int[] array) {
Arrays.sort(array);
boolean check = result.stream()
.anyMatch(a -> {
Arrays.sort(a);
return Arrays.equals(a, array);
});
if (!check) {
result.add(array);
}
}
It definitely feels hacky and wrong, but you could use a TreeSet
with a custom Comparator
. Depending on your needs this might actually work, but at least note that this is breaking the general contract of the Set
interface.
class Demo {
public static void main(String[] args) throws Exception {
Set<int[]> result = new TreeSet<>(new Hack());
int[] x = {1,2,3};
int[] z = {2,1,3};
int[] m = {2,1,3};
result.add(x);
result.add(z);
result.add(m);
for (int[] arr : result) {
System.out.println(Arrays.toString(arr));
}
}
}
class Hack implements Comparator<int[]> {
@Override
public int compare(int[] e1, int[] e2) {
int[] copy1 = Arrays.copyOf(e1, e1.length);
int[] copy2 = Arrays.copyOf(e2, e2.length);
Arrays.sort(copy1);
Arrays.sort(copy2);
return Arrays.compare(copy1, copy2);
}
}
Output:
[1, 2, 3]
If you are still on Java 8 use this Hack
implementation:
class Hack implements Comparator<int[]> {
@Override
public int compare(int[] e1, int[] e2) {
int[] copy1 = Arrays.copyOf(e1, e1.length);
int[] copy2 = Arrays.copyOf(e2, e2.length);
Arrays.sort(copy1);
Arrays.sort(copy2);
int cmp = Integer.compare(copy1.length, copy2.length);
if (cmp != 0) {
return cmp;
}
for (int i = 0; i < copy1.length; i++) {
cmp = Integer.compare(copy1[i], copy2[i]);
if (cmp != 0) {
return cmp;
}
}
return 0;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With