This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
I'm currently learning Java, I'm just curious about the code that I wrote a minute ago, it works, but I want to know if there is a better alternative (that isn't "use the clear method").
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add("A");
al.add("B");
al.add(5);
System.out.println(al.size());
Iterator i = al.iterator();
while (i.hasNext()) {
Object next = i.next();
System.out.println("Removing " + next.toString() + "...");
al.remove(next);
i = al.iterator();
}
System.out.println(al.size());
}
Especially, because I don't really know what can be in a specific position in an ArrayList (they contains objects of every kind), I used a generic "Object next" variable. I don't know if it is acceptable.
I know that there are methods to clear an ArrayList, I just wanted to try to understand how ArrayLists works, thank you.
You don't need to fetch each element before you remove it. You can simply remove elements by it's index:
ArrayList al = new ArrayList();
// ... add elements skipped...
// now clear it
int size = al.size();
for (int index = size-1; index >= 0; index--) {
al.remove(index);
}
but I want to know if there is a better alternative
Yes.
because I don't really know what can be in a specific position in an
ArrayList (they contains objects of every kind.
Make List<T> generic : it will allow you to add only some specific type of Object.
Replaced ArrayList al = new ArrayList(); by
List<String> al = new ArrayList<>();
Related
This question already has answers here:
How to get ordered stream from a list in reverse order in Java 8
(4 answers)
Java 8 stream reverse order
(30 answers)
Closed 4 years ago.
I am wondering if there are some kind of reverse_iterator(like c++) in List implementation like ArrayList<Integer>. i.e, I would like to iterate from the end of the List rather than from the beginning?
Is there any Java8 stream solution?
In java there is List Iterator
https://www.journaldev.com/13457/java-listiterator
// Substitute appropriate type.
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}
Another way you could have reversed the list is to use Collections.reverse
ArrayList<Integer> a = new ArrayList<>(); // assign some values here
a.forEach(System.out::println); // actual order
Collections.reverse(a);
a.forEach(System.out::println); // reverse order
Yes there is a option for reverse iteration in java.Below code works fine.
ArrayList<Integer> al = new ArrayList<>();
al.add(1);
al.add(2);
al.add(3);
al.add(4);
ListIterator<Integer> itr = al.listIterator(al.size());
System.out.println("Printing from last element ");
while (itr.hasPrevious()) {
System.out.println(itr.previous());
}
This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 7 years ago.
public static ArrayList<Character> removeDuplicates (ArrayList<Character> data) {
ArrayList<Character> newList = new ArrayList<Character>();
for (int i = 0; i < data.size() - 1; i++) {
if (!newList.contains(data.get(i)))
newList.add(0,(data.get(i)));
}
return newList;
}
Here is my code so far. I'm not understanding how this is not working
You can use a Set. A Set is a Collection that doesn't let duplicates of Objects.
I'm not sure what Object type your List is of, but let's say your were using String:
//replace all instances of 'String' with whatever Object type you are using
Set<String> mySet = new HashSet<>();
for(String s : data){
mySet.add(s);
}
Then if you want to send the data to a List, do:
ArrayList newList = new ArrayList(mySet);
There are 2 problems with your implementation.
You're not counting all of the items in the array. You should do either i <= data.size() - 1 or i < data.size(). Right now you're missing the last item.
You're not adding items to the end of the list. Instead, you're repeatedly overwriting the zeroth (first) value. EDIT: Sorry, that was incorrect. You're inserting at the beginning of the list, which will work but is inefficient for the most commonly used lists (e.g. ArrayList).
Here is the fixed version. The problem areas are commented out with /* */.
List<Object> newList = new ArrayList<Object>();
for (int i = 0; i < data.size() /* - 1 */ ; i++) {
if (!newList.contains(data.get(i)))
newList.add( /* 0, */ (data.get(i)));
}
return newList;
EDIT: Using contains(...) on a list is slow. You can optimize and simplify this by using a Set. A set is a collection which has unique values. Adding the same value twice has no effect. We can take it a step further and use a LinkedHashSet as the implementation class, which will maintain the same ordering as was in the original list.
return new ArrayList<Object>(new LinkedHashSet<Object>(data));
This question already has answers here:
Calling remove in foreach loop in Java [duplicate]
(11 answers)
Closed 9 years ago.
I am trying to create a huffman tree, and am in the middle of attempting to merge two trees. I can not figure out how to remove a Tree in my program without getting the "concurrent Modification Exception" because I am iterating over a list and attempting to remove from the list at the same time.
BinaryTree<Character, Integer> t1 = null;
BinaryTree<Character, Integer> t2 = null;
BinaryTree<Character, Integer> tFinal = null;
int treeSize = TREES.size();
for (int i = 0; i < treeSize; i++) {
for (BinaryTree<Character, Integer> t : TREES) {
System.out.println("treeSize " + treeSize);
System.out.println(t.getRoot().getElement()
+ " t.getRoot().getElement()");
// here I edited the merge function in Binary Tree to set
// the new root
// to have null value for value, and itemTwo for weight
System.out.println(t.getRoot().getValue() + " weight of tree \n");
t1 = t;
TREES.remove(t);
}
for (BinaryTree<Character, Integer> t : TREES){
t2 = t;
System.out.println(t);
}
int weight = t1.getRoot().getElement() + t2.getRoot().getElement();
tFinal.merge(null, weight, t1, t2);
}
Java prevents you from modifying collections in a loop. You will need to use an iterator.
If you want to modify the list while iterating over it, you need to use Iterator.
Below are some SO questions answering this:
Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop
How to modify a Collection while iterating using for-each loop without ConcurrentModificationException?
Your code doesn't compile, so we're limited in the way we can help you. But in general, the way you resolve this issue is to use an Iterator instead of a foreach loop.
For example, this gives a concurrent modification exception:
List<String> l = new ArrayList<String>(asList("a", "b", "c"));
for (String s : l) {
l.remove(s);
}
But this doesn't, and it gives you the result you'd want:
List<String> l = new ArrayList<String>(asList("a", "b", "c"));
for (Iterator<String> iterator = l.iterator(); iterator.hasNext(); ) {
String s = iterator.next();
iterator.remove();
}
System.out.println(l.size());
The latter will output "0".
A solution is to store in another list the items you want to remove, and then, after iterating, remove them.
This question already has answers here:
Removing an element from an Array (Java) [duplicate]
(15 answers)
Closed 9 years ago.
I have an array of Contact objects that has a MAX of 50 Contacts, but will have much less, so the array is initialized with a size of 50. But I need my method to remove the Contact and shift everything after it up. What I have seems to work at times, but not every time.
public Contact remove(String lstnm)
{
int contactIndex = findContactIndex(lstnm); // Gets the index of the Contact that needs to be removed
Contact contactToBeRemoved;
if(contactIndex == -1) // If the Contact is not in the Array
{
contactToBeRemoved = null;
}
else
{
contactToBeRemoved = Contact_List[contactIndex]; // Assigns the Contact that is going to be removed
for(int i = contactIndex; i < numContacts; i++) // From where the Contact was removed to the last Contact in the list
{
Contact_List[i] = Contact_List[i + 1]; // Shift all of the Contacts after the one removed down
}
numContacts -= 1; // One Contact is removed from the total number of Contacts
}
return contactToBeRemoved;
}
Arrays a fixed size you cannot resize them. ArrayList on the other hand auto resize each time you add a element.
So if I have a Array of 5 I can put 5 items in it, no more no less. One thing you can do is set objects in the Array to be null or 0.
Edit: With regards to your comment, just sort the Array. Look up a easy bubble sort algorithm in Java.
try
System.arraycopy(contactList, contactIndex + 1, contactList, contactIndex, contactList.length - contactIndex - 1);
Note that System.arraycopy is the most efficient way to copy / move array elements
your code would give exception at numContacts'th iteration since i+1 will go beyond size of array.
for(int i = contactIndex; i < numContacts-1; i++)
{
Contact_List[i] = Contact_List[i + 1];
}
Contact_List[Contact_List.length-1] = null;
Ps: its a very bad practice to use Array in such scenario, consider using ArrayList instead.
Why don't you convert your array into a List and use the remove(Object o) method that does exactly what you describe?
It would save you some time and some testing.
for such purpose use ArrayList
ArrayList<Contact> array = new ArrayList<Contact>(50);
creates a dynamic array with initial capacity of 50 (this can increase as more elements gets added to the ArrayList)
array.add(new Contact());
array.remove(contact); //assuming Contact class overrides equals()
ArrayList internally maintains an array and does re-sizing, restructuring as the elements are added or removed from it.
You can also use Vector<Contact> which is similar data-structure, but thread safe.
Array's become pretty useless when you know how to use arrayList, in my opinion. I suggest using arrayLists.
ArrayList tutorial
do like this when creating ht econtact arrayList:
import java.util.ArrayList;
public static void main(String args[]){
ArrayList<Contact> contacts = new ArrayList();
contacts.add(new Contact());
}
Use arrayLists, its the best way. Read tutorials, the are plenty of them.
I suggest it cause arralist are dynamic, that means you can add and remove items and it resized itself for you.
Hope I could help even if my answers isnt very complete
use collection rather than array so that you dont have to do all the shifting processes!
collection automatically shifts the elements and you dont have to worry about it!
you may do as follow,
ArrayList<Contact> list=new ArrayList<Contact>();
Contact c=new Contact();
Contact.Add(Contact);
Contact.remove(Contact);
and any more behaviours are available in ArrayList!
you may write you remove method as follows
public Contact remove(String lstnm)
{
Contact c=new Contact(1stnm);
Contact contactToBeRemoved=list.get(1);
List.remove(c);
return contactToBeRemoved;
}
but you have to override the equal() and compareTo() method of the object class in the Contact class!
otherwise nothing will work properly!
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}
When I run this code,I will throw a ConcurrentModificationException.
It looks as though when I remove the specified element from the list, the list does not know its size have been changed.
I'm wondering if this is a common problem with collections and removing elements?
I believe this is the purpose behind the Iterator.remove() method, to be able to remove an element from the collection while iterating.
For example:
Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("str3"))
iter.remove();
}
The Java 8 way to remove it from the List without Iterator is:
li.removeIf(<predicate>)
i.e.
List<String> li = new ArrayList<String>();
// ...
li.removeIf(st -> !st.equalsIgnoreCase("str3"));
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception
Taken from http://download.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html
yes people run into it -- the problem is you can't modify the list while iterating over it. I have used 2 alternatives in the past:
You can keep track of the indexes of the items you want to remove, and then remove them after you are done iterating.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
those options assume you have to iterate over the list to find the elements to remove -- useful in cases where the list elements are complex objects with properties you might test on.
In your particular case, you dont even need to iterate, as you can just use removeAll. Look at the API here. There are also nifty methods like retainAll that discard everything that is not in the argument. You can use remove/retain-like methods whenever the objects in the list implement equals and hashcode properly. If you cannot rely on equals/hashcode to identify equality between instances in your app, you will have to do the removal yourself....
Try this (Java 8):
list.removeIf(condition);
You could make a copy of list you want to remove element from, directly in for-each loop. For me, that is the simpliest way. Something like this:
for (String stringIter : new ArrayList<String>(myList)) {
myList.remove(itemToRemove);
}
Hope that will help you..
I think it is worth mentioning the Java 8 version
#Test
public void testListCur() {
List<String> li = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
li.add("str" + i);
}
li = li.stream().filter(st -> !st.equalsIgnoreCase("str3")).collect(Collectors.toList());
System.out.println(li);
}
ArrayList has field modCount - count of collection modifications
When you invoke method iterator() creates new object Itr. It has field expectedModCount. expectedModCount field initialize by modCount value. When you invoke
li.remove("str3");
modCount increments. When do you try access to li via iterator
checks that expectedModCount == modCount
and if it is false throws ConcurrentModificationException
Hence if you get iterator and after collection modified - iterator is considered not valid and you cannot use it.
I think that best answer is from bigdev.de, but i would like to add something to it(like if the item is removed from a list, maybe you would like to log that somewhere or something):
List<String> list = new ArrayList<>();
list.removeIf(a -> {
boolean condition = a.equalsIgnoreCase("some condition");
if(condition)
logger.info("Item removed from the list: " + a);
return condition;
});
I got this problem and I think the easier way is the same with the second way that hvgotcodes gave.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
List<String> finalLi = new ArrayList<String>();
for(String st:li){
if(st.equalsIgnoreCase("str3")){
// Do nothing
} else {
finalLi.add(st);
}
}
System.out.println(finalLi);
}
I looped a different way...
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(int i=0; i<li.size(); i++)
if(li.get(i).equalsIgnoreCase("str3"))
li.remove(i--);
System.out.println(li);
}