ArrayList.add works, but not ArrayList.remove - java

Creating an instance of an object (o) and adding it to an Arraylist (arrayList) works fine. However, the remove function doesn't work.
arrayList.add(o); // works
arrayList.remove(o); // does nothing
What am I missing?

ArrayList.remove() look like this:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
So, if your Object has default equals(), then this cant work. All object are diffrent. Add equals() to your Object class.

Related

Do I have to cast an Object object to a specific type before using it in my contains and equals method?

So I have a Hospital class and inside it, I have a method called remove(Object object) which checks what kind of Object the parameter input is. Then after finding the instance of the object I use my equals method to find the object in the ArrayList to remove. My question is, do I have to cast the object to the specific type before using it?
Something like this: .........equals((Patient) object))?
public boolean remove(Object object) {
if(object instanceof Department){
departments.remove(object);
return true;
}
if(object instanceof Patient){
for(int i = 0; i < departments.size(); i ++){
for(int j = 0; j < departments.size(); j ++) {
if (departments.get(i).getPatients().get(j).equals(object)) {
departments.get(i).getPatients().remove(j);
return true;
}
}
}
}
if(object instanceof Employee){
for(int i = 0; i < departments.size(); i ++){
for(int j = 0; j < departments.size(); j ++) {
if (departments.get(i).getEmployees().get(j).equals(object)) {
departments.get(i).getEmployees().remove(j);
return true;
}
}
}
}
return false;
}
No need to cast it. equals(object) and equals((Patient) object) resolve to the same method, if it is implemented correctly.
Dorian Gray's answer is fine, but a recommendation for refactoring:
implement equals and hashCode on your classes
make departments a collection, if it is not already
use Java's for-each loop (or streams)
So the double for-loops become
...
for (Department department : departments) {
if (department.getEmployees().contains(object)) {
department.getEmployees().remove(object);
return true;
}
}
...

Find array if it is subset of another array

This function should return true only if the parameter object is a subset of the calling object but it always returns true. How to fix it?
public boolean contains(FileCollection other) {
int i = 0;
int j = 0;
for (i = 0; i<other.files.length; i++) {
for (j = 0; j<this.files.length; j++) {
if ((other.files[i]).equals((this.files[j]))) //this refers to the equals method defined in File class
break;
}
if (j==this.files.length)
return false;
}
return true;//this method is in FileCollection class
}
(Since you didn't explicitly express what the data type of the array elements is, I'll assume it's File, inferred from comments.)
If you don't mind converting between data structures, maybe converting your arrays (temporarily) to Collections is the most simple way. For example, converting to List:
/* #param other
* #return true if the calling object contains
* all files in the parameter object, false otherwise
*/
public boolean contains(FileCollection other) {
List<File> myList = Arrays.asList(this.files);
List<File> otherList = Arrays.asList(other.files);
return myList.containsAll(otherList);
}
Based on your clarify of what to be considered as "contains" when duplicated items are allowed, I'd say you need to count the number of existence for each element. Here is how:
Based on the answer of #Eritrean , you can get and store the count to a map. I made modifications to check the count too:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
if (thisFrequency.entrySet().containsAll(otherFrequency).entrySet()) {
for (File entry : otherFrequency.entrySet()) {
if (thisFrequency.get(entry) < otherFrequency.get(entry))
return false;
}
return true;
}
return false;
}
For other.files contains this.files to hold, every this.file must be in other.files.
for (int j = 0; j < this.files.length; j++) {
boolean found = false;
for (int i = 0; i < other.files.length; i++) {
if (other.files[i].equals(this.files[j])) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
Not knowing the class of files, probably you can do:
for (String file : this.files) {
boolean found = false;
for (String otherFile : other.files) {
if (otherFile.equals(file)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
Or even
for (String file : this.files) {
boolean found = other.files.indexOf(file) != -1;
if (!found) {
return false;
}
}
return true;
There are nicer datastructures that speed things up, and have predefined methods for things like contains.
With duplicates
Comparator<File> comparator = new Comparator<File>() {
#Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator);
int otherI = 0;
for (File file : this.files.length) {
boolean found = false;
while (otherI < other.files.length) {
int comparison = comparator.compare(other.files[otherI], file);
++otherI;
if (comparison >= 0) {
found = comparison == 0;
break;
}
}
if (!found) {
return false;
}
}
return true;
By sorting both arrays you can synchronize the comparison at locations in both arrays. The above handles duplicates.
Apart from the #renyuneyun suggestion to convert your arrays into Lists you could also make use of the String contains method
public boolean contains(FileCollection other) {
String myList = Arrays.toString(this.files);
String otherList = Arrays.toString(other.files);
return myList.contains(otherList);
}
Of course both of these suggestions are not the optimum solutions from the complexity point of view, but are for sure the shortests :)
What about using a map with File as key and frequency as value:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
return thisFrequency.entrySet().containsAll(otherFrequency.entrySet());
}
Only this answer works for me: (Credit to #Joop Eggen for the Comparator part)
public boolean contains(FileCollection other) {
Comparator<File> comparator = new Comparator<File>() {
#Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareToIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareToIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getPermissions(), rhs.getPermissions());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator); //THIS AND THE COMPARATOR SORT THE ARRAYS BASED ON ALL FILE ATTRIBUTES
int i = 0;
int j = 0;
if (this.files.length<other.files.length)
return false;
while (i<other.files.length && j<this.files.length) {
if (!(this.files[j].equals(other.files[i])))
j++;
else {
j++;
i++;
}
}
if (i<other.files.length)
return false;
else
return true;
}

Adding new element to array in java

I'm making a store in java and I'm trying to add a new item to an array, but I can't figure out how to make it work. add.items(i); won't work because that's only for ArrayList, and a requirement for this task is that I have to use an array. The purpose of this function is it checks if there is an empty space in the array, which has a maximum size of 10, and it adds an item if it's not full.
public boolean addItem (Item i){
for (int i = 0; i < items.length; i++) {
if (items[i] == null) {
add.items(i);
return true;
}
return false;
}
}
Your code won't work because you are using duplicate variables i.
Try this instead:
public boolean addItem (Item item) {
// Rename loop variable
for (int x = 0; x < items.length; x++) {
if (items[x] == null) {
// Asign the incoming item to items array in case this position is empty
items[x] = item;
return true;
}
}
return false;
}

How to remove an object from arrayList

I implemented both add() and remove() methods from my ArrayList Class.
public void add(Object obj) {
if(data.length - currentSize <= 5) {
increaseListSize();
}
data[currentSize++] = obj;
}
public Object remove(int index){
if(index < currentSize){
Object obj = data[index];
data[index] = null;
int tmp = index;
while(tmp < currentSize){
data[tmp] = data[tmp+1];
data[tmp+1] = null;
tmp++;
}
currentSize--;
return obj;
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
However, I don't know how to remove the specific index of my ArrayList of members.
if(temp[0].equals("ADD")) {
memberList.add(member);
fileOut.writeLine(member.toString());
fileLog.writeLine("New member " + member.toString() + " was succesfully added");
}
**else if(temp[0].equals("REMOVE")) {
//memberList.remove(index)
}**
}
Is there any suggestion of how should I get to remove the index of an object of the memberList? Can I modify my remove() method so that I could directly remove the object instead?
One possibility is to overload the existing remove-method with one that takes an Object-parameter. In the method body you have to iterate through the objects of the list and determine the index of the passed object. Then the existing remove-method is called using the previously determined index to remove the corresponding object.
The following implementation removes the first occurrence of the specified object from the list. The removed object is returned. If the list does not contain the object null is returned.
public Object remove(Object obj){
int index = -1;
for (int i = 0; i < data.length; i++) {
if (data[i] == obj) {
index = i;
break;
}
}
if (index != -1) {
return remove(index);
}
return null;
}

Checking an array for descending order

I am writing code to check if my array is in ascending or descending order. If the boolean 'ascending' is true, then I check if it is ascending. If it is false, then I check for descending. I need help checking whether the array is descending or not... I have the code to check ascending which is written below:
protected boolean isSorted(boolean ascending) {
boolean result = false;
if (ascending) {
for (int i=0;i<data.length-1;i++) {
if(data[i] < data[i+1]) {
result = true;
} else if(data[i] > data[i+1]) {
result = false;
}
}
} else {
//code to check for descending order
}
}
The first part of the if (the "ascending" check) is wrong, it should be:
for (int i = 0; i < data.length-1; i++) {
if (data[i] > data[i+1]) {
return false;
}
}
return true;
Conversely, the descending check should be (and notice that it's enough to change the direction of the comparison operator):
for (int i = 0; i < data.length-1; i++) {
if (data[i] < data[i+1]) {
return false;
}
}
return true;
In both cases, you have to break out of the loop as soon as you find a single pair of numbers that do not hold the ascending-or-descending property, and only return true after the loop exits.
You can cheat and do it in one loop if you like and remove one addition:
protected boolean isSorted(boolean ascending) {
for (int i = 1; i < data.length; i++) {
if (data[i-1] == data[i]) {
continue;
}
if ((data[i-1] > data[i]) == ascending) {
return false;
}
}
return true;
}
NOTE: I am building on the code by #OscarLopez so upvote his if you upvote mine.
To check if ArrayList<Integer> is in descending order try this:
boolean isSorted(ArrayList<Integer> list){
boolean sorted = true;
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1) >= (list.get(i)) ) {
sorted = true;
} else {
return false;
} // if else ends
} // for "i" ends
return sorted;
}

Categories

Resources