Create an unique ID based on the content of the object - java

i would like to know if it is possible in java,to create an ID for an element inside an object, so if another object is generated with the same element i can check if it was created priviously.
Example1
`
{
int[][] cha = new int[3][3];
cha[0][0] = 8;
cha[0][1] = 1;
cha[0][2] = 3;
cha[1][0] = 4;
cha[1][1] = 0;
cha[1][2] = 2;
cha[2][0] = 7;
cha[2][1] = 6;
cha[2][2] = 5;
int[][] hol = new int[3][3];
hol[0][0] = 8;
hol[0][1] = 1;
hol[0][2] = 3;
hol[1][0] = 4;
hol[1][1] = 0;
hol[1][2] = 2;
hol[2][0] = 7;
hol[2][1] = 6;
hol[2][2] = 5;
HashSet<int[][]> k = new HashSet();
k.add(cha);
System.out.println(k.contains(cha));
System.out.println(k.contains(hol));
}`
In this case, I wil get the values "true, false" even though both matrix are the same ( I know it is because HashSet does reference to the memory address and not the object.)
I want to be able to create the matrix a second time and determinate if it was already created.
Thanks.

Wrap it in a class and define your own equals() and hashcode()

I know it is because HashSet does reference to the memory address and not the object
No, that's not the reason. The reason is that an array is only equal to itself, because arrays don't override the Object.equals() and Object.hashCode() methods, that HashSet uses to check which elements it already contains.
To get the behavior you want, you need to wrap the matrix into your own class which overrides equals() and hashCode(), in order to tell when two matrices are equal. Make sure to never modify any element of a matrix once it has been stored into the HashSet:
public final class Matrix {
private int[][] elements;
public Matrix(int[][] elements) {
this.elements = elements;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Matrix)) {
return false;
}
Matrix m = (Matrix) o;
return Arrays.deepEquals(this.elements, m.elements);
}
#Override
public int hashCode() {
return Arrays.deepHashCode(elements);
}
}
And now you can do
HashSet<Matrix> set = new HashSet<>();
Matrix m1 = new Matrix(cha);
k.add(m1);
System.out.println(set.contains(m1));
Matrix m2 = new Matrix(hol);
System.out.println(set.contains(m2));

Related

What is the best way to check if ALL values in a range exist in an array? (java)

I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}

How to extend bloom filter when it runs out of space?

I am studying bloom filter algorithm. The concept is quite straight forward, below is my simple implementation of "bloom filter structure" in Java.
My question is how to extend the capacity when the bitset is almost full? If I change the size of the bitset, obvious I have to consider the hash functions again, and I have to re-arrange those exist elements.
Second thought is to initialize another instance of bloom filter.
But these are only my thoughts, anyone can help with these? Thanks!
public class BloomFilter {
private static final int DEFAULT_SIZE = 2 << 24;
private static final int[] seeds = {7, 11, 13, 31, 37, 61};
static class SimpleHash {
private int cap;
private int seed;
public SimpleHash(int cap, int seed) {
this.cap = cap;
this.seed = seed;
}
public int hash(String str) {
int result = 0;
int length = str.length();
for (int i = 0; i < length; i++) {
result = seed * result + str.charAt(i);
}
return (cap - 1) & result;
}
}
private BitSet bitSet;
private SimpleHash[] hashes;
public BloomFilter() {
bitSet = new BitSet(DEFAULT_SIZE);
hashes = new SimpleHash[seeds.length];
for (int i = 0; i < seeds.length; i++) {
hashes[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}
public void add(String str) {
for (SimpleHash hash : hashes) {
bitSet.set(hash.hash(str), true);
}
}
public boolean mightContains(String str) {
if (str == null) {
return false;
}
boolean result = true;
for (SimpleHash hash : hashes) {
result = result && bitSet.get(hash.hash(str));
}
return result;
}
}
Bloom filter works only when you know number of elements to be inserted in advance. Usually you have desired false positive error P and number of elements to be inserted N, and you use them to compute number of hash functions H and capacity M.
If you don't know number of elements in advance, then the only way is to store all elements somewhere externally as you add them to bloom filter (for example, in file). When number of added elements exceeds safe threshold N, you:
delete your current bloom filter instance
create new bloom filter instance with new M and H derived from P and N*2 (or N*3/2)
read all elements from file and insert them in new bloom filter instance

Java storing objects in a multidimensional array

I'm attempting to store objects in a multidimensional array in an attempt to save each position in a game boards 'state', however after the loop which is supposed to set each instance to it's own parameters they all end up the same variables. Did I not link the correct array or set it up wrong?
There's also a lot of "square.something should be accessed in a static way".
Is square.var or World[x][y].var the correct way for referencing the objects variables?
public static void generateMap() {
MapSquare[][] World = new MapSquare[10][10]; //2D array init.
//Choose a square for the home position.
Random homeRandom = new Random();
int HomeX = homeRandom.nextInt(10);
int HomeY = homeRandom.nextInt(10);
//Chooses a key room.
int KeyX = homeRandom.nextInt(10);
int KeyY = homeRandom.nextInt(10);
//Loop through the objects and set each's parameters.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
MapSquare square = new MapSquare();
//World[i][j] = square;
//Calculate the level of the square from the distance to home.
int distX = HomeX - i;
int distY = HomeY - j;
int CalcX = Math.abs(distX); //Convert to positive if negative.
int CalcY = Math.abs(distY); //Convert to positive if negative.
//Generate contents of the square.
int newRandom = random.nextInt(5) + 1;
switch(newRandom) {
case 1: // Spawn a monster only.
{
square.monster = true;
square.treasure = false;
square.trap = false;
square.home = false;
square.peekable = false;
square.key = false;
square.mapLevel = CalcX + CalcY;
//Generate the monsters stats.
Monster monster = new Monster();
monster.setLevel(square.mapLevel);
monster.setMaxHealth(monster.getLevel() * 5);
monster.setHealth(monster.getMaxHealth());
monster.setDamage(monster.getLevel() * 2);
break;
}
}
}
}
//Generate home square.
World[HomeX][HomeY].monster = false;
World[HomeX][HomeY].treasure = false;
World[HomeX][HomeY].trap = false;
World[HomeX][HomeY].home = true;
World[HomeX][HomeY].peekable = true;
World[HomeX][HomeY].key = false;
World[HomeX][HomeY].mapLevel = 0;
World[HomeX][HomeY].visited = true;
}
The static keyword basically means that a method can be used independently of a specific instance of the class it is in. Such as the Math.abs(int i) function you are using, you don’t have to create an instance of the Math class to use it.
If you intend to use a class to store data it is generally a bad idea to include static methods as they would not be able to access that data.

Array of arbitrary dimension as method parameter

I have a simple converter method for an array from boolean to int:
public static int[] convert1dToInt (boolean[] x) {
int la = x.length;
int[] y = new int[la];
for (int a = 0; a < la; a++) {
if (x[a]) {
y[a] = 1;
} else {
y[a] = 0;
}
}
return y;
}
Now I have the same method for 2-dimensional arrays:
public static int[][] convert2dToInt (boolean[][] x) {
int la = x.length;
int lb = x[0].length;
int[][] y = new int[la][lb];
for (int a = 0; a < la; a++) {
for (int b = 0; b < lb; b++) {
if (x[a][b]) {
y[a][b] = 1;
} else {
y[a][b] = 0;
}
}
}
return y;
}
How can I generalize those methods for arrays of arbitrary dimension without writing all the methods by hand?
This is possible, but reflection and recursion are both inevitable:
import java.lang.reflect.Array;
public class ArrayTransfer {
private static int getArrayDimension(Object array) {
Class<?> clazz = array.getClass();
int dimension = 0;
while (clazz.isArray()) {
clazz = clazz.getComponentType();
dimension += 1;
}
if (clazz != boolean.class) {
throw new IllegalArgumentException("Base array type not boolean");
}
return dimension;
}
// Transfers a boolean array of the specified dimension into an int
// array of the same dimension.
private static Object transferToIntArray(Object booleanArray, int dimension) {
if (booleanArray == null) {
return null;
}
// Determine the component type of the new array.
Class<?> componentType;
if (dimension == 1) {
componentType = int.class;
} else {
// We have a multidimensional array; the dimension of the component
// type is one less than the overall dimension. Creating the class
// of an array of an unknown dimension is slightly tricky: we do
// this by creating a 0 x 0 x ... x 0 array (with dimension - 1
// zeros) and then getting the class of this array. Handily for us,
// int arrays are initialised to all zero, so we can create one and
// use it straight away.
int[] allZeroDimensions = new int[dimension - 1];
componentType = Array.newInstance(int.class, allZeroDimensions).getClass();
}
// Create the new array.
int length = Array.getLength(booleanArray);
Object newArray = Array.newInstance(componentType, length);
// Transfer the elements, recursively if necessary.
for (int i = 0; i < length; ++i) {
if (dimension == 1) {
Boolean value = (Boolean)Array.get(booleanArray, i);
Array.set(newArray, i, (value.booleanValue()) ? 1 : 0);
}
else {
Object oldChildArray = Array.get(booleanArray, i);
Object newChildArray = transferToIntArray(oldChildArray, dimension - 1);
Array.set(newArray, i, newChildArray);
}
}
return newArray;
}
// Transfers a boolean array of some dimension into an int
// array of the same dimension.
public static Object transferToIntArray(Object booleanArray) {
if (booleanArray == null) {
return null;
}
int dimension = getArrayDimension(booleanArray);
return transferToIntArray(booleanArray, dimension);
}
}
This should work with any number of dimensions up to 255 - I gave it a quick test with 5 and it seemed to work. It should also work with 'jagged' arrays, and with nulls.
To use it, call ArrayTransfer.transferToIntArray(...) with your boolean array, and it will return the corresponding int array. You will of course need to cast the return value of this method to the relevant int array type.
There's certainly scope for improving this. In particular, it would be nicer if some cache of the various array classes was kept, rather than having to instantiate empty arrays just to get their class.
You can use a conditional recursivity on the type of the passed parameter and you use convert1dToInt for the dimension one , then you collect the result in one object, in the given context you will be forced to pass just an object of type Object and return an Object then you cast it , here is a small code that present idea of the recursive function that just print the value of the elements in the array :
public static void convertDimN(Object o) {
if (o.getClass().isArray() && Array.get(o, 0).getClass().isArray()) {
// is o a two dimentional array
for (int i = 0; i < Array.getLength(o); i++) {
convertDimN(Array.get(o, i));
}
} else
for (int i = 0; i < Array.getLength(o); i++) {
System.out.println(Array.get(o, i));
}
}
This would be your first method:
public static int[] convert1dToInt (boolean[] x) {
//int la = x.length; is useless since you are accessing an object member and not a method
int[] y = new int[x.length];
for (int a = 0; a < x.length; a++) {
y[a] = x[a] ? 1 :0;
}
return y;
}
Simply reuse your code - I had not much time since it is my lunch break so I don#t know if all is correct but the way should fit:
public static int[][] convert2dToInt (boolean[][] x) {
int[][] y = new int[x.length][];
for (int a = 0; a < x.length; a++) {
y[a] = convert1dToInt (x[a]) ;
}
return y;
}
Ok, this solution was not the answer for the problem since I did not read exactly what has been asked. Sorry for that. As far as I know a generalized method is not possible as long as you are working with primitive datatypes. This is because you can't add an int[] as a member for an int[]. So you should then work with Object[], Boolean[] and Integer[] but I don't know how you want to work with that. I don't think it is sensible to write such a method because when you are able to convert such a data-structure how do you want the targets to be accessed. Since you do not know how many dimensions your array will have you can't write generic methods to access the members. I will try to write a solution for that since I want to know if I find an other possible solution. Am I right that the question is, if it is possible and not if it is reasonable?
I think we can find the best solution for that if you tell us the usecase you want to have this code for. As I said, when I have more time later on I'll try to find another solution.

Using an int variable for list placements

I'm not sure if my wording is correct. I'm hoping it'll be more clear with this.
Integer[] Performed = new Integer[3];
public String dived(){
while (this.numberAttempts<3){
int n = this.numberAttempts;
int k = Dive.chosenRandomly();
this.Performed[n] = k ;
numberAttempts += 1;
}
return null;
}
I want the values of k(the random number) to be kept in a list so I know which numbers were chosen.
Is there a way for me to add values into the list in a while loop?
It works if I replace the n in [] with an integer<3.
Just use some list for example ArrayList and add random Integer to it.
List<Integer> Performed = new ArrayList<Integer>();
public String dived(){
while (this.numberAttempts<3){
int n = this.numberAttempts;
int k = Dive.chosenRandomly();
this.Performed.add(k) ;
numberAttempts += 1;
}
return null;
}

Categories

Resources