RemoveIf with lambda expression to remove only one occurence of integer - java

I need to remove only one occurence of an integer in a ArrayList of integers. My code right now removes all integers with a specific value.
list.removeIf(s -> s.equals(data));
If I have for example:
ArrayList<Integer> i = new ArrayList<Integer>();
i.add(1);
i.add(1);
i.add(3);
i.add(5);
and I want to remove only the first 1 or the second 1. Not both.

Solution
Use the List#remove method. That is exactly what it was made for, from the documentation:
Removes the first occurrence of the specified element from this list, if it is present (optional operation). If this list does not contain the element, it is unchanged. [...]
boolean wasRemoved = list.remove(data);
Removing ints
However, you might have a minor issue here. Your data type is Integer and data is probably of type int. And there is already a method with the signature List#remove(int) (documentation) which will remove the element at the given index, not the element itself.
You can bypass this by explicitly boxing your data to an Integer, which is what you actually have stored in the list:
boolean wasRemoved = list.remove((Integer) data);
Or directly make the data variable of type Integer instead of int.

Just use remove method from the list.remove(new Integer(data)), by the implementation you can see that it removes the first element then exits:
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}

Related

3 dimensional arraylist argumets are not applicable

I am trying to make a program in Java about the Tabulation method. For those unfamiliar, one of the steps in Tabulation method is to group binaries with the same number of 1's digits. So we put the group with the same number of 1's digit in a arraylist. So if we have five different groups (1st group containing no 1's digits, 2nd group containing one 1's digits, and so on), we store them in another arraylist. Thus an arraylist of an arraylist.
In the Tabulation method, we compare the elements from each group with the elements from the proceeding group. Each time we find a similar element from the next group (exactly one digit that differs), then we put them in a new list. This list is again grouped from the number of 1's digit. Thus, we have an arraylist of an arraylist of an arraylist.
What I have here is a part of my code:
allTables.add(new ArrayList<ArrayList<String>>().set(count, new ArrayList<String>().add(mintermBinaries[i])));
allTables is just an arraylist of an arraylist of an arraylist. The integer count determines the number of 1's digit a binary has and sets it in that index, and finally mintermBinaries[i], is the ith index of the array that contains all binaries in ascending order. The whole code is within a for loop.
The problem is it won't compile because according to Eclipse, the arguments are not applicable. I don't know why.
After thinking about this a lot, I'm not sure if a three dimensional array is even a good thing to do. Can anyone help? What is a better way to solve this?
new ArrayList<ArrayList<String>>().set(
count,
new ArrayList<String>().add(mintermBinaries[i]))
The second argument of set(), which is supposed to be an ArrayList<String> (since you're calling it on an ArrayList<ArrayList<String>>), is the expression
new ArrayList<String>().add(mintermBinaries[i])
The type of this expression is the type of the value returned by the method add(). And add() returns a boolean. And a boolean is not an ArrayList<String>.
Don't try to write all your code in a single line. Replace that with
List<ArrayList<String>> listOfLists = new ArrayList<ArrayList<String>>();
ArrayList<String> innerList = new ArrayList<String>();
innerList.add(mintermBinaries[i]);
listOfLists.set(count, innerList);
As returninig result of List#add() and List#set() are different from what you expect, to use such one-liners, you need additional helper methods:
// Appends an item to the end of the list.
// Instead of `boolean`, returns modified list itself
static <T> List<T> add(List<T> list, T item) {
list.add(item);
return list;
}
// Sets an item to arbitrary position in `List`, expanding if needed.
// Instead of replaced item, returns modified list itself
static <T> List<T> set(List<T> list, int index, T item) {
if (list.size() <= index) {
for (int i = list.size(); i <= index; i++)
list.add(null);
}
list.set(index, item);
return list;
}
then you can write your code in one line:
add(allTables, set(new ArrayList<List<String>>(), count, add(new ArrayList<String>(), mintermBinaries[i])));
Although this is not very elegant and may be even confusing in your particular case (I'd also prefer to call List.add() and .set() sequentially), such approach may happen more clean and efficient in some situations.

Can Iterator remove an item not equal to a particular value from the list?

It seems that when I attempt to iterate through a list I cannot remove all items not equal to the one that I wish to keep.
For example, I have the following code:
for (Iterator<Alphabet> iter = list.iterator(); iter.hasNext();) {
Alphabet item = iter.next();
if (!item.letter().equals("C")) {
iter.remove();
}
}
I expect that list will be a list of one Alphabet element with the letter "C" but that is not the case. I actually get an empty list. How do I change this in order to get my expected result?
Edit
To answer the question in the title: yes, an Iterator can remove an item not equal to a particular value.
The remove() operation simply removes the current object. If the right objects are not being removed, the logic deciding when to remove is the problem, not the Iterator or its operations.
Original Answer
If item.letter() returns a Character type, then item.letter().equals("C") will always return false.
If you look at the javadoc for Character.equals(), it says:
The result is true if and only if the argument is not
null and is a Character object that
represents the same char value as this object.
So trying to compare it to a String ("C") will always fail and remove the object.

Pass An Array as Argument Having a Different Start Index

How can I pass arrays in Java where I can indicate a different start index (0th index) for the array argument. In C++, you can pass arrays like this
myMethed(myArray + 3); // passing method where begin index is 4th element
...
void myMethod(int* arr) {
int val = arr[0]; // refers to the 4th element
int val2 = arr[1]; // 5th element
}
How can I do something similar in Java. I tried copying a subset of the array using Arrays.copyOfRange but I don't want a separate copy but the same array with a different start index.
Of course I can do this:
myMethod(int[] arr, int startIndex) {
int val = arr[startIndex];
int val2 = arr[startIndex + 1];
}
But are there other ways without declaring a separate parameter for start index?
Thanks a lot.
but the same array with a different start index.
In Java, an array is an object whose size is defined at the point it is initialized. The starting index is always zero and the size is fixed. These two cannot be altered after memory has been allocated. In Java same array means same object and not a memory space.
Java doesn't allow you to slice the allocated memory as a new array. So, you will always need to create another array, or explicitly pass the starting index to the method you are calling.
In general, prefer collections over arrays. Your particular need can be solved by using Lists instead:
myMethod(List<Integer> list) {
int val = list.get(0);
int val2 = list.get(1);
}
...
List<Integer> myList = ...;
myMethod(myList.subList(3, myList.size()));
From the List.subList documentation:
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
(emphasis mine)
You can create an iterator, move it to the required position and pass it as a method argument.
what about this ?
Integer myarr[] = new Integer[] { 1, 2, 3, 4 };
System.out.println(Arrays.toString(Arrays.asList(myarr).subList(2, myarr.length).toArray(new Integer[2])));

Getting Index of an item in an arraylist;

I have a Class called AuctionItem. The AuctionItem Class has a method called getName() that returns a String. If I have an ArrayList of type AuctionItem, what is the best way to return the index of an item in the ArrayList that has a specific name?
I know that there is an .indexOf() function. The parameter for this function is an object. To find the item that has a name, should I just use a for loop, and when the item is found, return the element position in the ArrayList?
Is there a better way?
I think a for-loop should be a valid solution :
public int getIndexByname(String pName)
{
for(AuctionItem _item : *yourArray*)
{
if(_item.getName().equals(pName))
return *yourarray*.indexOf(_item)
}
return -1;
}
Yes.you have to loop it
public int getIndex(String itemName)
{
for (int i = 0; i < arraylist.size(); i++)
{
AuctionItem auction = arraylist.get(i);
if (itemName.equals(auction.getname()))
{
return i;
}
}
return -1;
}
Basically you need to look up ArrayList element based on name getName. Two approaches to this problem:
1- Don't use ArrayList, Use HashMap<String,AutionItem> where String would be name
2- Use getName to generate index and use index based addition into array list list.add(int index, E element). One way to generate index from name would be to use its hashCode and modulo by ArrayList current size (something similar what is used inside HashMap)
.indexOf() works well.
If you want an example here is one:
ArrayList<String> example = new ArrayList<String>();
example.add("AB");
example.add("CD");
example.add("EF");
example.add("GH");
example.add("IJ");
example.add("KL");
example.add("MN");
System.out.println("Index of 'AB': "+example.indexOf("AB"));
System.out.println("Index of 'KL': "+example.indexOf("KL"));
System.out.println("Index of 'AA': "+example.indexOf("AA"));
System.out.println("Index of 'EF': "+example.indexOf("EF"));
will give you an output of
Index of 'AB': 0
Index of 'KL': 5
Index of 'AA': -1
Index of 'EF': 2
Note: This method returns -1 if the specified element is not present in the list.
for (int i = 0; i < list.length; i++) {
if (list.get(i) .getName().equalsIgnoreCase("myName")) {
System.out.println(i);
break;
}
}
To find the item that has a name, should I just use a for loop, and when the item is found, return the element position in the ArrayList?
Yes to the loop (either using indexes or an Iterator). On the return value, either return its index, or the item iteself, depending on your needs. ArrayList doesn't have an indexOf(Object target, Comparator compare)` or similar. Now that Java is getting lambda expressions (in Java 8, ~March 2014), I expect we'll see APIs get methods that accept lambdas for things like this.
You could implement hashCode/equals of your AuctionItem so that two of them are equal if they have the same name. When you do this you can use the methods indexOf and contains of the ArrayList like this: arrayList.indexOf(new AuctionItem("The name")). Or when you assume in the equals method that a String is passed: arrayList.indexOf("The name"). But that's not the best design.
But I would also prefer using a HashMap to map the name to the item.
Rather than a brute force loop through the list (eg 1 to 10000), rather use an iterative search approach :
The List needs to be sorted by the element to be tested.
Start search at the middle element size()/2 eg 5000
if search item greater than element at 5000, then test the element at the midpoint between the upper(10000) and midpoint(5000) - 7500
keep doing this until you reach the match (or use a brute force loop through once you get down to a smaller range (eg 20 items)
You can search a list of 10000 in around 13 to 14 tests, rather than potentially 9999 tests.

Why is my ArrayList.remove(id) call not working?

I have an ArrayList, which includes a number of items I want to remove. I have the ids of the items to remove stored in another list. Figured the following code should work trivially, but for some reason, the remove() calls are returning a false value:
ArrayList<Integer> toRemove = new ArrayList<Integer>();
ArrayList<JCheckBox> al = new ArrayList<JCheckBox>();
/* Code that adds a bunch of items to al, and a few integers to toRemove */
System.out.println("Size before removing: " + al.size());
for (int i = toRemove.size() - 1; i >= 0; i--) {
System.out.println("Removing id: " + toRemove.get(i) + ": ");
System.out.println(al.get(toRemove.get(i)));
System.out.println(al.remove(toRemove.get(i)));
}
System.out.println("Size after removing: " + al.size());
I'd get it if the get() call also returned a false value, but it does actually return the object in question. What am I missing here?
The output of the code above:
Size before removing: 3
Removing id: 2:
javax.swing.JCheckBox[...]
false
Size after removing: 3
My guess is you are having a problem with the fact that remove() is overloaded with both int and Object, while get() only takes an int. Try remove(toRemove.get(i).intValue()).
remove(Object) from AbstractCollection will search through the list and remove the given object, which won't be there because you are sending it an Integer and the list only has JCheckBoxs. You are trying to call remove(int), but because you are giving it an Integer, the Object overload is called instead. By converting the Integer to an int, you avoid this problem
Also, can you always be sure the Id in toRemove always equals the index? If toRemove is not in greatest to least order, it won't be.
There are two problems with your code.
First, the wrong "toRemove" method is getting invoked. When you call "toRemove.get(i)", the return value is autoboxed into a java.lang.Integer, instead of an int. Therefore, java.util.List#remove(Object) is called instead of java.util.List#remove(int). It's trying to remove an Integer object, and returns false.
If you cast the Integer to an int, the desired method will get invoked.
Second problem: each time you remove an element of the list, the indexes of all subsequent elements change, as those elements are "shifted" down. There are several ways to get around this. One is to sort your list of indexes in descending order. Another would be to use a set of indexes, create a new array, and copy into the new array only those elements whose index is not in the set.
javax.swing.JCheckBox[...]?
Also, try remove elements by Objects value, like here:
http://www.easywayserver.com/blog/java-remove-element-in-arraylist/

Categories

Resources