I have a problem where I retrieve and element from a list (list1), and modify one of the parameters in the element and then add it to another list (list2). When I do this to the final item in list1, it will sometimes modify the parameters of the elements in list2.
This function is called once per generation, but it is not until about the 8th generation when I start to see this happen. It has affect anywhere from 2 to 16 elements in list2.
Any ideas where my screw up might be? Here's a block of code I wrote to illustrate the problem. The problem occurs in the section where I check count==0.
public void sampleCode (List list) {
List differentList = new ArrayList();
Individual element;
Individual differentelement;
int i = 0;
int count = 0;
for(i = 0; i < list.size(); i++) {
element = (Individual) list.get(i) ;
// does some checking to see if this meets criteria
// this is sorta pseudo code
if(probability == true) {
element.setDoMutation(true);
count++;
}
//always add this element to differentList
//even if no changes are made to the element
differentList.add(i,element);
}
//need to make sure one elements has mutation=true;
if(count == 0) {
differentelement = (Individual) list.get((list.size()-1));
//setting this element field changes the contents of
//different list.
differentelement.setDoMutation(true);
differentList.set((list.size()-1), differentelement);
}
}
In Java, a variable doesn't hold an object. It holds an object reference (i.e. a pointer to an object). Getting an object fom a list and putting it in another list doesn't make a copy of the object. Both lists simply have a pointer to the same object. So, of course, if you modify the contents of the object, both lists will have the object modified.
Side note: You should use parameterized types (i.e. List<Individual> rather than List), and avoid declaring variables at the beginning of your methods as you would do in C. Only declare a variable when you need it. This will make the code much clearer, and reduce the scope of your variables.
Are you sure that the block
//need to make sure one elements has mutation=true;
if(count == 0) {
differentelement = (Individual) list.get((list.size()-1));
//setting this element field changes the contents of
//different list.
differentelement.setDoMutation(true);
differentList.set((list.size()-1), differentelement);
}
has to be inside the loop
for(i = 0; i < list.size(); i++) {
...
}
I suspect it has to be moved after the loop in order to work correctly.
Related
I have a homework to do in java about ArrayList and Generics types.
I have 2 classes :
-> CoupeDeA
-> TableauPartiel
CoupeDeA is just a describer from where to where an array is cut.
(It contains only two private integer variables "begin" and "end")
TableauPartiel is the class where the ArrayList is.
My problem is I need to create a method in TableauPartiel like this :
public TableauPartiel<E> coupe(CoupeDeA coupe)
And the TableauPartiel returned needs to be a reference of my intial TableauPartiel. Example :
Integer[] arr = {8,7,6,5};
TableauPartiel<E> tab = new TableauPartiel<>(arr);
TableauPartiel<E> tab2 = tab.coupe(1,3);
tab2.set(1,45);
This code is supposed to set 45 at index 1 of my tab2 and at the same time set 45 at index 2.
But I tried many different ways and I managed to get the sublist, but it is not pointing to my original ArrayList.
For example, I tried something like this :
private ArrayList<E> tableau;
...
public TableauPartiel<E> coupe(Coupe coupe)
throws IndexOutOfBoundsException {
if (coupe.getBegin() >= 0 && coupe.getEnd() <= tableau.size()) {
TableauPartiel<E> tab = new TableauPartiel<>((E[]) new Object[coupe.getEnd()-coupe.getBegin()]);
for (int i = 0; i < coupe.getEnd()-coupe.getBegin(); ++i) {
tab.set(i, this.get(coupe.getBegin()+i));
}
return tab;
} else {
throw new IndexOutOfBoundsException();
}
}
How can I do to get a sublist which refers to his original ArrayList?
I've found a solution for my code with the subList method and by switching the signature of my ArrayList to List but my teacher doesn't want us to use subList finally.
Here is my code with the subList method :
TableauPartiel<E> tab;
if (coupe.getDebut() >= 0 && coupe.getFin() <= taille()) {
if (coupe.getFin() == -1)
tab = new TableauPartiel<>(tableau.subList(coupe.getDebut(),taille()));
else
tab = new TableauPartiel<>(tableau.subList(coupe.getDebut(),coupe.getFin()));
return tab;
} else {
throw new IndexOutOfBoundsException();
}
}
Few small things first:
stick to English words in your code. Especially in names of classes, functions, variables, etc - names have to reveal intentions (without Google Translate). Best not to obtain a bad habit by letting yourself do otherwise.
I am not so sure how your Coupe is expected to work (is 0 a legal min number or 1?) but coupe.getEnd() <= tableau.size() might get out of hand
Now my suggestion for the solution:
I suggest you modify your TableauPartiel class to have start and end integer fields in addition to private ArrayList<E> tableau; reference you already have. Maybe add a new 'copy constructor' accepting an instance of
TableauPartiel (from which you can copy reference to tableau) and two int values indicating which part of the original tableau you can use (trick here is to also look at start and end values of the object you're 'sublisting' from). That way, when you're calling #coupe you can check for validity of the input numbers (as you already do) and simply return a new TableauPartiel object with a reference to this and method params - start and end values. Add some indexes manipulation logic using those start and end to whatever methods your TableauPartiel has and you should be good to go.
I have a class Section with several methods including methods get_key() and get_angle(). Items of type Section are added to a hashtable implemented in class Hashtable.
According to my task I should delete such elements from the hashtable which have bigger value of function get_angle() than given_value.
class Hashtable{
private Section[] hash_array; //array of cells of the hashtable
public int size;
public void remove_given(double given_value)
{
for(int i = 0; i < size; i++)
{
if (hash_array[i] != null)
{
double value = hash_array[i].get_angle(); //value of needed function to compare
if (value > given_value)
{
int key_ = hash_array[i].get_key(); //get key for the item in order to delete it
Delete(key_); //delete item
}
}
}
}
}
But the method doesn`t delete any elements. I checked the method Delete() separately and it works just fine as well as other methods called on this method . I really need to figure it out. So I will be grateful for your help.
Debug your code, does it enter the for-loop. How do you initialize the value of size variable? If you forget to initialize it by default it will be zero. It is better to get the size from the hash_array.length.
For one thing you're using the uninitialized global var, size, the size used in the for loop needs to be the size of the Hash collection. Also how is the Hash initialized? Does it contain what you think? I'd follow the aforementioned suggestion to step through the code with a debugger, perhaps the keys aren't what you think they are...
My Problem
I have a fixed-size ArrayList which contains custom variables. Despite of the ArrayList having a fixed size, sometimes a lot of them will actually be null. The thing is that I need to return the ArrayList without the null variables inside it. One important thing to note: the ArrayList will have all of its non-null items first, and then all of the nulls below them, e.g., the elements are not mixed. Example: [non-null, non-null, .... null, null, null]
My workaround
I though of creating a for-loop that checked (from last to first index) each of the elements inside the ArrayList to determine if it's null or not. If is null, then I'd call this code:
for (i = size-1; i >=0 ; i--) {
groupList = new ArrayList<>(groupList.subList(0, i));
}
My question
If the ArrayList is too big, this method might me particularly slow (or not?). I was wondering if there exists a better, more performance-friendly solution. AFAIK the .subList method is expensive.
You can have a variant of binary search, where your custom comparator is:
Both elements are null/not null? They are equal
Only one element is null? The none null is "smaller".
You are looking for the first null element.
This will take O(logn) time, where n is the size of the array.
However, taking the sublist of the ArrayList that is none null (assuming you are going to copy it to a new list object), is going to be linear time of the elements copied, since you must "touch" each of them.
This gives you total time complexity of O(logn + k), where k is number of non null elements, and n is the size of the array.
Following all of your outstanding advices, I modified the original method so that I can take the last (first) ever null item position and call the .subList method just once. And here it is:
int lastNullIndex = size - 1;
for (i = lastNullIndex; i >= 0; i--) {
if (null == groupList.get(i)) {
lastNullIndex = i;
} else {
break;
}
}
groupList = new ArrayList<>(groupList.subList(0, lastNullIndex));
return groupList;
If you think it can be further modified so as to allow for a better performance, let us know.
Is this usage of elements of an ArrayList:
for(int i=0; i<array_list.size(); i++){
Object obj = array_list.get(i);
//do **lots** of stuff with **obj**
}
faster than this one:
for(int i=0; i<array_list.size(); i++){
//do **lots** of stuff with **array_list.get(i)**;
}
It depends on how many times array_list.get(i) is called in the second code. If it is called only once, there is no difference between both methods.
If it's invoked multiple times, saving the value in a variable may be more efficient (it depends on the compiler and the JIT optimizations).
Sample scenario where the first method may be more efficient, compiled using Oracle JDK's javac compiler, assuming the list contains String objects:
for(int i=0; i<array_list.size(); i++){
String obj = array_list.get(i);
System.out.println(obj);
if(!obj.isEmpty()) {
String o = obj.substring(1);
System.out.println(o + obj);
}
}
In this case, obj is saved as a local variable and loaded whenever it is used.
for(int i=0; i<array_list.size(); i++){
System.out.println(array_list.get(i));
if(!array_list.get(i).isEmpty()) {
String o = array_list.get(i).substring(1);
System.out.println(o + array_list.get(i));
}
}
In this case, multiple invokation for List.get are observed in the bytecode.
The performance difference between getting once and a local variable is almost always neglible. But... if you insist on doing it the hardcore way, this is the fast way to go:
ArrayList<Object> array_list = ...
// cache list.size() in variable!
for (int i=0, e=array_list.size(); i < e; ++i) {
// get object only once into local variable
Object object = array_list.get(i);
// do things with object
}
It caches the lists size into a local variable e, to avoid invoking array_list.size() at each loop iteration, as well as each element in the loop to avoid get(index) calls. Be aware that whatever you actually do with the objects in the loop will most likely be by orders of magnitude more expensive than the loop itself.
Therefore, prefer code readability and simply use the advanced for loop syntax:
ArrayList<Object> array_list = ...
for (Object object : array_list) {
// do things with object
}
No hassles, short and clear. Thats worth far more than a few saved clock cycles in most cases.
if have the following problem:
I have a List which i am going through using the enhanced for loop. Every time i want to remove sth, out of the list, i get a ConcurrentModificationException. I already found out why this exception is thrown, but i don`t know how i can modify my code, so that its working. This is my code:
for(Subject s : SerData.schedule)
{
//Checking of the class is already existing
for(Classes c : s.classes)
{
if(c.day == day &c.which_class == which_class)
{
int index = getclassesindex(s.classes, new Classes(day, which_class));
synchronized (s) {
s.classes.remove(index);
}
}
}
//More code....
}
I also tried out this implementation.
for(Subject s : SerData.schedule)
{
//Checking of the class is already existing
Iterator<Classes> x = s.classes.iterator();
while(x.hasNext())
{
Classes c = x.next();
if(c.day == day &c.which_class == which_class)
{
int index = getclassesindex(s.classes, new Classes(day, which_class));
synchronized (s) {
s.classes.remove(index);
}
}
}
//More code....
}
not working either...
Is there a common used, standard solution? (Hopefully sth. that is not obvious :D )
The main reason this issue occurs is because of the semantic meaning of your for-each loop.
When you use for-each loops, the data structure that is being traversed cannot be modified.
Essentially anything of this form will throw this exception:
for( Object o : objCollection )
{
// ...
if ( satisfiesSomeProperty ( o ) )
objList.remove(o); // This is an error!!
// ...
}
As a side note, you can't add or replace elements in the collection either.
There are a few ways to perform this operation.
One way is to use an iterator and call the remove() method when the object is to be removed.
Iterator <Object> objItr = objCollection.iterator();
while(objItr.hasNext())
{
Object o = objItr.next();
// ...
if ( satifiesSomeProperty ( o ) )
objItr.remove(); // This is okay
// ...
}
This option has the property that removal of the object is done in time proportional to the iterator's remove method.
The next option is to store the objects you want to remove, and then remove them after traversing the list. This may be useful in situations where removal during iteration may produce inconsistent results.
Collection <Object> objsToRemove = // ...
for( Object o : objCollection )
{
// ...
if ( satisfiesSomeProperty ( o ) )
objsToRemove.add (o);
// ...
}
objCollection.removeAll ( objsToRemove );
These two methods work for general Collection types, but for lists, you could use a standard for loop and walk the list from the end of the list to the front, removing what you please.
for (int i = objList.size() - 1; i >= 0; i--)
{
Object o = objList.get(i);
// ...
if ( satisfiesSomeProperty(o) )
objList.remove(i);
// ...
}
Walking in the normal direction and removing could also be done, but you would have to take care of how incrementation occurs; specifically, you don't want to increment i when you remove, since the next element is shifted down to the same index.
for (int i = 0; i < objList.size(); i++)
{
Object o = objList.get(i);
// ...
if ( satisfiesSomeProperty(o) )
{
objList.remove(i);
i--;
}
//caveat: only works if you don't use `i` later here
// ...
}
Hope this provides a good overview of the concepts and helps!
Using Iterator.remove() should prevent the exception from being thrown.
Hm if I get it right you are iterating over a collection of classes and if a given class matches some criteria you are looking for the its index and try to remove it?
Why not just do:
Iterator<Classes> x = s.classes.iterator();
while(x.hasNext()){
Classes c = x.next();
if(c.day == day && c.which_class == which_class) {
x.remove();
}
}
Add synchronization if need be (but I would prefer a concurrent collection if I were you), preferably change the "==" to equals(), add getters/setters etc. Also the convention in java is to name variables and methods using camelCase (and not separating them with "_").
Actually this is one of the cases when you have to use an iterator.
From the javadoc on ConcurrentModificationException:
"if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception."
So within your
for (Classes c : s.classes)
you are executing
s.classes.remove(index)
and the iterator is doing just what its contract says. Declare the index(es) in a scope outside the loop and remove your target after the loop is done.
Iterator<Classes> classesIterator = s.classes.iterator();
while (classesIterator.hasNext()) {
Classes c = classesIterator.next();
if (c.day == day && c.which_class == which_class) {
classesIterator.remove();
}
}
There is no general solution for Collection subclasses in general - most iterators will become invalid if the collection is modified, unless the modification happens through the iterator itself via Iterator.remove().
There is a potential solution when it comes to List implementations: the List interface has index-based add/get/set/remove operations. Rather than use an Iterator instance, you can iterate through the list explicitly with a counter-based loop, much like with arrays. You should take care, however, to update the loop counter appropriately when inserting or deleting elements.
Your for-each iterator is fail-fast and this is why remove operation fails as it would change the collection while traversing it.
What implementation of List interface are you using?
Noticed synchronisation on Subject, are you using this code concurrently?
If concurrency is the case, then I would recommend using CopyOnWriteArrayList. It doesn't need synchronisation and its for-each iterator doesn't throw ConcurrentModificationException.