Store and find if a certain array is already stored - java

My program checks multiple boolean arrays (length 30 each) and I would like to know if I already checked that array. I thought the best way to handle this problem would be to store all the arrays and search for the new array in the set of all the arrays but I don't know what structure I should use. At first, I though hashtable would be the best but it looks like I can't use them with arrays. I looked for set and list but I have no clue what to use !
Edit/clarification: Hey it's my first question here and I'm surprised how many answers I received, thanks a lot ! Lot of people says they are unsure about what exactly I'm looking for so I'll try to clarify:
I have multiple boolean arrays of length 30 where the order is important ( order of elements in the array).
I receive one array at a time and I want to check if I already received the same array (same element, same order). I don't need to store them( I don't need any index, I don't want to know how many arrays I received), don't need anything except to know if I already received the array.

A boolean array is basically a list of bits. Since array size is 30, and an int is a 32-bit value, you can convert the array into an int. With a long you could support arrays up to 64 in size.
So, first convert your array to an int:
private static int toBits(boolean[] array) {
if (array.length > 32)
throw new IllegalArgumentException("Array too large: " + array.length);
int bits = 0;
for (int i = 0; i < array.length; i++)
if (array[i])
bits |= 1 << i;
return bits;
}
Then keep track using a Set<Integer>:
private Set<Integer> alreadySeen = new HashSet<>();
private boolean firstTime(boolean[] array) {
return ! this.alreadySeen.add(toBits(array));
}
This provides a very fast and low-memory implementation that can handle lots of boolean arrays.

You can create a Wrapper class that holds array (content) and a flag. And, instead of storing array of arrays, you can store array of objects of this class. Have a look at the example below:
public class ArrayWrapper {
private boolean checked;
private boolean[] content;
/**
* #return the checked
*/
public boolean isChecked() {
return checked;
}
/**
* #param checked the checked to set
*/
public void setChecked(boolean checked) {
this.checked = checked;
}
/**
* #return the content
*/
public boolean[] getContent() {
return content;
}
/**
* #param content the content to set
*/
public void setContent(boolean[] content) {
this.content = content;
}
}
Now, you can create a List<ArrayWrapper> or ArrayWrapper[], iterate through it and set checked to true once the array (content) is checked.

Use Arrays.equals(array1, array2)
This method returns true if the two specified arrays of booleans are equal to one another. Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal.
I’m giving you a brute force solution.
List<boolean[]> arrs = new ArrayList<>();
while (true) {
boolean[] receivedArr = receive();
for (boolean[] existingArr : arrs) {
if (Arrays.equals(existingArr, receivedArr)) {
drop(receivedArr);
break;
}
arrs.add(receivedArr);
}
}

You can try an adjacency list or perhaps an array/arraylist of an Object that you call 'Pair' for example where this object has two attributes , the first is an array(the array you checked or didn't check yet) and the second attribute is a boolean value that denotes whether this array has been visited or not.

You can use an array :)
If you have n arrays, then create a boolean array of size n. Let's call it checked[].
So if checked[5] == true, you already checked the fifth array.
Another option would be to use the index 0 of each array as the 'checked flag'.

Thanks for your clarification!
HashMap is still a good answer using Arrays.hashCode() to create your key object. Like so:
HashMap<Integer, Boolean> checked = new HashMap<>();
/**
* Returns true if already checked; false if it's new
*/
public boolean isChecked(Boolean [] array) {
int hashCode = Arrays.hashCode(array);
Boolean existing = checked(hashCode);
if (existing == null) {
checked.put(hashCode, true);
return true;
}
return false;
}

Related

How do you find the index of the value(a String Value) from an arrayList? [duplicate]

For an Android app, I have the following functionality
private ArrayList<String> _categories; // eg ["horses","camels"[,etc]]
private int getCategoryPos(String category) {
for(int i = 0; i < this._categories.size(); ++i) {
if(this._categories.get(i) == category) return i;
}
return -1;
}
Is that the "best" way to write a function for getting an element's position? Or is there a fancy shmancy native function in java the I should leverage?
ArrayList has a indexOf() method. Check the API for more, but here's how it works:
private ArrayList<String> _categories; // Initialize all this stuff
private int getCategoryPos(String category) {
return _categories.indexOf(category);
}
indexOf() will return exactly what your method returns, fast.
ArrayList<String> alphabetList = new ArrayList<String>();
alphabetList.add("A"); // 0 index
alphabetList.add("B"); // 1 index
alphabetList.add("C"); // 2 index
alphabetList.add("D"); // 3 index
alphabetList.add("E"); // 4 index
alphabetList.add("F"); // 5 index
alphabetList.add("G"); // 6 index
alphabetList.add("H"); // 7 index
alphabetList.add("I"); // 8 index
int position = -1;
position = alphabetList.indexOf("H");
if (position == -1) {
Log.e(TAG, "Object not found in List");
} else {
Log.i(TAG, "" + position);
}
Output: List Index : 7
If you pass H it will return 7, if you pass J it will return -1 as we defined default value to -1.
Done
If your List is sorted and has good random access (as ArrayList does), you should look into Collections.binarySearch. Otherwise, you should use List.indexOf, as others have pointed out.
But your algorithm is sound, fwiw (other than the == others have pointed out).
Java API specifies two methods you could use: indexOf(Object obj) and lastIndexOf(Object obj). The first one returns the index of the element if found, -1 otherwise. The second one returns the last index, that would be like searching the list backwards.
There is indeed a fancy shmancy native function in java you should leverage.
ArrayList has an instance method called
indexOf(Object o)
(http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html)
You would be able to call it on _categories as follows:
_categories.indexOf("camels")
I have no experience with programming for Android - but this would work for a standard Java application.
Good luck.
the best solution here
class Category(var Id: Int,var Name: String)
arrayList is Category list
val selectedPositon=arrayList.map { x->x.Id }.indexOf(Category_Id)
spinner_update_categories.setSelection(selectedPositon)
Use indexOf() method to find first occurrence of the element in the collection.
The best way to find the position of item in the list is by using Collections interface,
Eg,
List<Integer> sampleList = Arrays.asList(10,45,56,35,6,7);
Collections.binarySearch(sampleList, 56);
Output : 2

Saving memory and CPU in java loops

this (obvious) code i've writen works well, but for testing purposes, i should make it work for a "one million" sized array in a reasonable time by saving CPU Cycles and saving as much memory as i can.
any suggestions please?
!!! the array is arranged in ascending order !!!
import java.util.Arrays;
class A {
static boolean exists(int[] ints, int k) {
for(int integer : ints){
if(integer == k){
return true;
}
}
return false;
}
Since your array is in ascending order, one thing you could do (i think) is to make a binary search instead of a linear search.
You could use a Set<Integer> that relies on hashing rather than an array where you iterate sequentially.
static boolean exists(Set<Integer> ints, int k) {
return ints.contains(k);
}
You could convert the array to a Set and pass it to the method as many times as required :
Set<Integer> set = Arrays.stream(ints).boxed().collect(Collectors.toSet());
boolean isExist = exists(set, 15);
...
isExist = exists(set, 5005);
...
isExist = exists(set, 355);

Implementing an equals() method to compare contents of two 'bag' objects

I am working on a school assignment. The objective is to practice GUI's, clone() methods, and using/ modifying existing code. I am trying to write an equals method in the way the instructor desires-- by using a clone of the object, removing items from the bag (returns boolean based on success or failure to remove).
The bag is represented in an array, and should return true in cases such as {1,2,3} and {3,2,1}, ie order does not matter, only the number of each number present in the arrays.
Here is the issue
It works in most cases, however there is a bug in cases where the bags contain numbers as such: {1,1,2} and {1,2,2} and other similar iterations. It is returning true instead of false.
I believe it has something to do with the remove() method we are supposed to use. If i understand it correctly, it is supposed to put the value at the 'end' of the array and decrease the manyItems counter (this is a variable for number of items in the array, because array.length is by default in the constructor 10.)
The code is largely written by another person. We had to import the existing files and write new methods to complete the task we were given. I have all the GUI part done so i will not include that class, only the used methods in the IntArrayBag class.
A second pair of eyes would be helpful. Thanks.
public class IntArrayBag implements Cloneable
{
// Invariant of the IntArrayBag class:
// 1. The number of elements in the bag is in the instance variable
// manyItems, which is no more than data.length.
// 2. For an empty bag, we do not care what is stored in any of data;
// for a non-empty bag, the elements in the bag are stored in data[0]
// through data[manyItems-1], and we don�t care what�s in the
// rest of data.
private int[ ] data;
private int manyItems;
public IntArrayBag( )
{
final int INITIAL_CAPACITY = 10;
manyItems = 0;
data = new int[INITIAL_CAPACITY];
}
public IntArrayBag clone( )
{ // Clone an IntArrayBag object.
IntArrayBag answer;
try
{
answer = (IntArrayBag) super.clone( );
}
catch (CloneNotSupportedException e)
{ // This exception should not occur. But if it does, it would probably
// indicate a programming error that made super.clone unavailable.
// The most common error would be forgetting the "Implements Cloneable"
// clause at the start of this class.
throw new RuntimeException
("This class does not implement Cloneable");
}
answer.data = data.clone( );
return answer;
}
public int size( )
{
return manyItems;
}
public boolean remove(int target)
{
int index; // The location of target in the data array.
// First, set index to the location of target in the data array,
// which could be as small as 0 or as large as manyItems-1; If target
// is not in the array, then index will be set equal to manyItems;
for (index = 0; (index < manyItems) && (target != data[index]); index++)
// No work is needed in the body of this for-loop.
;
if (index == manyItems)
// The target was not found, so nothing is removed.
return false;
else
{ // The target was found at data[index].
// So reduce manyItems by 1 and copy the last element onto data[index].
manyItems--;
data[index] = data[manyItems];
return true;
}
}
//I added extra variables that are not needed to try to increase readability,
//as well as when i was trying to debug the code originally
public boolean equals(Object obj){
if (obj instanceof IntArrayBag){
IntArrayBag canidate = (IntArrayBag) obj; // i know this can be changed, this was required
IntArrayBag canidateTest = (IntArrayBag) canidate.clone(); //this was created
//as a clone because it was otherwise referring to the same memory address
//this caused items to be removed from bags when testing for equality
IntArrayBag test = (IntArrayBag) this.clone();
//fast check to see if the two objects have the same number of items,
//if they dont will return false and skip the item by item checking
if (test.size() != canidateTest.size())
return false;
//the loop will go through every element in the test bag it will
//then remove the value that is present at the first index of the test bag
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
int check = test.data[i];
//remove() returns a boolean so if the value is not present in each bag
//then the conditional will be met and the method will return false
boolean test1 = test.remove(check);
boolean test2 = canidateTest.remove(check);
if (test1 != test2)
return false;
}//end for loop
// if the loop goes through every element
//and finds every value was true it will return true
return true;
}//end if
else
return false;
}//end equals
}
I cannot see the big picture, as I havent coded GUIs in Java before, however, as far as comparing 2 int[] arrays, I would sort the arrays before the comparison. This will allow you to eliminate problem cases like the one you stated ( if sorting is possible), then apply something like:
while(array_1[index]==array_2[index] && index<array_1.length)
{index++;}
and find where did the loop break by checking the final value of index
Is it explicitly stated to use clone? You can achieve it easily by overriding the hashCode() for this Object.
You can override the hashCode() for this object as follows:
#Override
public int hashCode() {
final int prime = 5;
int result = 1;
/* Sort Array */
Arrays.sort(this.data);
/* Calculate Hash */
for(int d : this.data) {
result = prime * result + d;
}
/* Return Result */
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || this.getClass() != obj.getClass()){
return false;
}
return false;
}
If you want to continue using your implementation for equals to compare test and CandidateTest then also you can compute unique hashes and make decision based on the results.
Here is the code snippet:
/* Assuming that you have put size comparison logic on top
and the two objects are of same size */
final int prime = 31;
int testResult = 1;
int candidateTestResult = 1;
for(int i = 0; i < test.size(); i++) {
testResult = prime * testResult + test.data[i];
candidateTestResult = prime * candidateTestResult + candidateTest.data[i];
}
/* Return Result */
return testResult == candidateTestResult;
I believe the problem is in this line:
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
The problem here is that test and canidateTest are the clones that you made, and you are removing elements from those bags. And any time you remove an element from the bag, the size will decrease (because you decrease manyItems, and size() returns manyItems). This means you're only going to go through half the array. Suppose the original size is 4. Then, the first time through the loop, i==0 and test.size()==4; the second time, i==0 and test.size()==3; the third time, i==2 and test.size()==2, and you exit the loop. So you don't look at all 4 elements--you only look at 2.
You'll need to decide: do you want to go through the elements of the original array, or the elements of the clone? If you go through the elements of the clone, you actually never need to increment i. You can always look at test.data[0], since once you look at it, you remove it, so you know test.data[0] will be replaced with something else. In fact, you don't need i at all. Just loop until the bag size is 0, or until you determine that the bags aren't equal. On the other hand, if you go through the elements of this.data (i.e. look at this.data[i] or just data[i]), then make sure i goes all the way up to this.size().
(One more small point: the correct spelling is "candidate".)
Maybe you should try SET interface
view this in detail :http://www.tutorialspoint.com/java/java_set_interface.htm
A set object cannot contains duplicate elements, so it's suitable for your assignment than build your own class.
For example:[1,1,2] and [1,2,2]
you can use this to test whether they are equal
arr1 = {1,1,2}
arr2 = {1,2,2}
Set<Integer> set = new HashSet<Integer>();
for(int i : arr1){//build set of arr1
if(set.contains(i)==false){
set.add(i)
}
}
for(int i:arr2){
if(set.contains(i)==false){
System.out.println('not equal');
break;
}
}
Hope this is helpful.

Java - ArrayList default initial values

When you create an arraylist of type Integer in Java what are the default values? I need to check if an arraylist is full and I was going to get the size of the array then get the value at the last index and check if it was the default value.
Is there a better way? What would be the default value?
Hope that makes sense. Cheers
int size = a.size();
int last = a.get(size);
if( last == null )
{
return true;
}else{
return false;
}
Edit;
Is it possible to create an ArrayList with a max size that you can not go over to stop it dynamically expanding?
When you create an ArrayList and you use size() would that return the actual size or the amount of elements in the arraylist?
When doing this to create a max size would the default values be null?
public boolean isFull()
{
int size = a.size();
int last = 0;
try{
last = a.get(size-1);
}catch (Exception e){
}
if( last == null )
{
return true;
}else{
return false;
}
}
I currently have this, how does it look? Does this make sense now?
When you declare an ArrayList it is empty. It is also a dynamic container meaning it will grow so for you to ask if it is "full" is more of a constraint you'd need to add to your code.
So, if you want to achieve a goal like you describe.
List<Integer> list = new ArrayList<Integer>();
int MAX_ELEMENTS = 5; //Set this to however you want to constrain the datatype
public boolean addElement(Integer value) {
if (list.size() < MAX_ELEMENTS) {
list.add(value);
return true;
} else {
return false;
}
}
public boolean isFull() {
return (list.size() == MAX_ELEMENTS);
}
public Integer getLast() {
if (!list.isEmpty())
return list.get(list.size()-1);
else
return null;
}
As others have stated though, if you generate a list with a preset size as such:
List<Integer> list = new ArrayList<Integer>(10);
You'd have a list of 10 elements large all being null in value. Should you add additional elements the list will still grow larger than 10 elements unless you constrain it like I did above.
If you haven't actually added Integers to the ArrayList, then any get() on the list will return an IndexOutOfBoundsException.
The size() method returns the number of elements in the list (i.e. how many you have added to it), not the current capacity.
By default ArrayList capacity is 10. All of them are null by default until you add your elements into it. But calling size() will give you number of elements that you have added. It wont give 10 as result(default null values will not be considered). Twist here is if you add null values to the list then they are included while calculating size(). Example if you add 3 valid Integers and 2 null values into the list then size() will return 5. Eclipse debugging will help you in finding this dynamic increasing of its capacity.
When you create an ArrayList, inside the ArrayList class, there is an array of elements. Those elements are set to null because they do not refer to any instance of an Integer object. Bare in mind, that isn't the same as an int.
Moreover, an ArrayList doesn't get full. It is dynamic, and will increase in size when it needs to.
Edit: in response to your edit about setting a maximum size, if you want a maximum size then I'm not sure why you'd want an arraylist. But if you want to stick with an ArrayList class, I would create my own class that is a subclass of arraylist, and override the add method with a check to ensure the value of size() isn't over a fixed amount.
There is not such thing like "full" ArrayList. The size() method will return the number of elements it currently holds.
Do you want to simply constraint the list to a given size, or do you want to check if it is larger than a given size?
Check if list is larger than:
if (list.size() > limit)
System.out.println("List too large");
Its not possible to constraint the size of an ArrayList - you can however create your own subclass of ArrayList that does just that:
public class LimitedList<E> extends ArrayList<E> {
private int limit;
public LimitedList(int limit) {
this.limit = limit;
}
public boolean add(E e) {
// only add if the limit is not exceeded
if (size() < limit)
super.add(e);
}
// overwriting the addAll()-methods is left as an excercise to the reader
}
You only need to decide what the list should DO when one attempts to add more elements than the limit allows. Either just ignore the elements or throw an Exception.
ArrayLists have no default values. If you give the ArrayList a initialCapacity at initialization, you're just giving a hint for the size of the underlying array—but you can't actually access the values in the ArrayList until you add the items yourself.
Any List implementation has a isEmpty() method you can use.

question on java list remove

The method public boolean remove(Object o) of List removes an object from list but does not shift the elements following.Just nulls the object value.
IMHO this is an uninintuitive design choice since the size of the list before and after removal remains the same.
Is there an elegant way to get a list with the elements shifted?
Thanks
No, that's not what it does. The element is removed and all indices following it are reduced by one. What makes you think it acts differently?
According to the Java API here it sais that the remove function of List DOES shift
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
EDIT:
Main class:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<A> x = new ArrayList<A>();
A one = new A("one");
A two = new A("two");
A three = new A("three");
A four = new A("four");
A five = new A("five");
A six = new A("six");
A seven = new A("seven");
A eight = new A("eight");
A nine = new A("nine");
A ten = new A("ten");
x.add(one);
x.add(two);
x.add(three);
x.add(four);
x.add(five);
x.add(six);
x.add(seven);
x.add(eight);
x.add(nine);
x.add(ten);
for(A item:x){
System.out.println(item.getStr());
}
x.remove(four);
Iterator<A> i = x.iterator();
while(i.hasNext()){
A item = i.next();
System.out.println(item.getStr());
}
}
}
The A Class:
public class A {
private String str;
public A(String x){
this.str = x;
}
public String getStr(){
return this.str;
}
}
works perfectly! no null pointer exception.
This is how it should be done. the first For loop is the alternative syntax for what i did wit the Iterator object. Actually Java automatically translates the first for loop in something that looks like the while loop.
If you look at ArrayList remove implementation, it uses a local method fastRemove(index) as follows:-
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
It does use arraycopy which is a proof that you get whole new list of fresh objects and not the null filled in between. Is this a proof?
The contract for java.util.List implies that calling remove will cause the size() to be decremented. If you're talking specifically about java.util.ArrayList then you might be right about the internal array not shifting its elements, but this is an implementation detail that shouldn't matter to you in 99% of all cases. If it still does matter, then you're trying to optimize for a specific situation and you should probably implement your own List or use something like java.util.LinkedList.
Either your observation is wrong or you are using some other kind of List implementation (and not ArrayList) that doesn't shift the elements to the right of the element being removed. Can you post your code?
If you look at the java.util.ArrayList source code in JDK8, you will see that the remove(Object o) method effectively copies the elements to the right of the element being removed, to the same array starting from the index of the element being removed. Look at the ArrayList source code for more info:
If all you need is an array of the data, then just call toArray().

Categories