I have a collection and some elements inside it. If I remove one element, then is there any way I can get it back or recover it? Please guide me if it is possible and how.
Check this example:
List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
if(//delete condition){
toRemove.add(a);
}
}
The element will be cleared from the memory by garbage collection as soon as there's no reference to it. This means that you need to keep at least one reference pointing at the actual element to have it alive in the memory. Otherwise consider it gone.
You need to store a reference to the element before you remove it. If there is no further reference to the item it may be collected by the garbage collector and there is no way to find it again. To store a reference either set a temporary variable equal to the object before you delete it; or certain collections such as ArrayLists allow you to save the object as you delete it if you use the Remove() method that takes an integer (the index of the element).
Related
I have a very simple question that I would like to ask. There are 2 ways by which you initialize a variable :
1.
List<SalesReturnJson> salesReturnJsons=new LinkedList<>();
salesReturnJsons=salesRepository.findSales();
2.
List<SalesReturnJson> salesReturnJsons=salesRepository.findSales();
So in this 2 scenerios how is the memory allocated and In the second scenerio which implementation(LinkedList or ArrayList) of List is called.
Any help will be highly appreciated.
If in the first scenario the second line is exactly below the first line, the "new" statement would have no effect. You create an empty LinkedList, put a reference on it, then you change the reference to point to another List (I suppose findSales returns a List) and finally the garbage collector of java will erase the empty LinkedList, since there is no reference to it anymore.
In the second scenario you return a List (as I suppose) and put a reference to this List.
In both cases an object returned by salesRepository.findSales() will be assigned to your variable. Since the implementation is the same in both cases, without knowing the actual implementation we can only say that the object will be of the same class in both cases, however, creating an object and then re-assigning the variable to another reference as in your first example makes little sense. The second will achieve the same result, but with reduced effort.
Both scenarios end up with exactly the same List in your salesReturnJsons variable, with the List type being the one returned by salesRepository.findSales(). From the code given, we can't tell what type is actually returned from this method.
The only difference is, the first scenario creates an absolutely unnecessary empty LinkedList, stores it into your salesReturnJsons variable, and immediately replaces it by the list from salesRepository.findSales(), making the LinkedList garbage. So, please use the second version.
If (for whatever special reason) your intent might be to have a LinkedList of the salesRepository.findSales() results, then you could do:
List<SalesReturnJson> salesReturnJsons=
new LinkedList<SalesReturnJson>(salesRepository.findSales());
That will copy the elements from the method result into a fresh LinkedList, then you are sure about the List type.
But the typical code snippet would be your version 2.
I have a problem with understanding one thing.
I have:
List<Map> resultList = new ArrayList<Map>();
Then this resultList is filled with some data
resultList.addAll(somemethod(something, something, else));
Later in the method I have this kind of code:
Map timeSpan = someMethod(resultList, date);
timeSpan.put(KEY_ART, VALUE_ART);
timeSpan.put(KEY_TIMESPAN, true);
So I have a question now. If Map timeSpan is a map referenced to an element of List<Map> resultList, is using the put() method on the timeSpan map affecting the element in resultList?
I am asking this question cause a collegue told me that this is working this way - modifying an element in timeSpan is also modyfying this element in resultList. She is far more experienced, and I don't just want to believe her but I want to understand why it is working this way.
You have to remember that resultList is a reference to an object. You can copy this reference around and use it in many way, in many places but there is only one object. This means when you alter the object, there is only one view of this object.
Java objects are always instantiated as a reference to a memory space. If you create a second object from the first object, both will point to the same memory space:
Map a = new HashMap();
Map B=b = a;
Here, we first create an instance A which points to a HashMap which is created somewhere in memory. Next, we create an instance of Map b and have it reference to the same memory space as Map a. Now, when we change map b, these changes will also be made to Map a, since they point to the same memory construct.
In you case, you have a List this in itself is a memory construct. Each item in the list references a seperate Map. These are each also created somewhere in memory. The moment you retreive a Map from the list, you retreive the reference to the memory space where the actual map is located. After that, it works exactly as the example.
addAll() will copy all the elements to the current list from the Collection/List you passed as an argument to this method. In your case, as each element is a reference to Map object, after copying, you have 2 references pointing to same Map object, so changes done using any one reference are visible through the other one.
The short answer is yes, put() for timeSpan is affecting resultList, because when a method returns a Map, which is got from the List, it returns a reference to the heap where map elements are located.
I am creating an ArrayList of objects using generics. Each thread does come calculating and stores the object in the the array list.
However when looking at the ArrayList which is static and volatile all the object attributes are set as null. My thoughts are something to do with the garbage collector removing the instances in the threads so once the threads have finished there is no reference to them.
Any help would be really helpful?
The garbage collector will not remove instances1 from an array list. That is not the problem.
The problem is most likely that you are accessing and updating the array list object without proper synchronization. If you do not synchronize properly, one thread won't always see the changes made by another one.
Declaring the reference to the ArrayList object only guarantees that the threads will see the same list object reference. It makes no guarantees about what happens with the operations on the list object.
1 - Assuming that the array list is reachable when the GC runs, then all elements that have been properly added to the list will also be reachable. Nothing that is reachable will be deleted by the garbage collector. Besides, the GC won't ever reach into an object that your application can still see and change ordinary references to null.
I was recently looking into freeing up memory occupied by Java objects. While doing that I got confused about how objects are copied (shallow/deep) in Java and how to avoid accidently clearing/nullifying objects while they are still in use.
Consider following scenarios:
passing a ArrayList<Object> as an argument to a method.
passing a ArrayList<Object> to a runnable class to be processed by a thread.
putting a ArrayList<Object> into a HashMap.
Now in these case, if I call list = null; or list.clear();, what happens to the objects? In which case the objects are lost and in which cases only the reference is set to null?
I guess it has to do with shallow and deep copying of objects, but in which cases does shallow copying happens and in which case does deep copy happens in Java?
Firstly, you never set an object to null. That concept has no meaning. You can assign a value of null to a variable, but you need to distinguish between the concepts of "variable" and "object" very carefully. Once you do, your question will sort of answer itself :)
Now in terms of "shallow copy" vs "deep copy" - it's probably worth avoiding the term "shallow copy" here, as usually a shallow copy involves creating a new object, but just copying the fields of an existing object directly. A deep copy would take a copy of the objects referred to by those fields as well (for reference type fields). A simple assignment like this:
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = list1;
... doesn't do either a shallow copy or a deep copy in that sense. It just copies the reference. After the code above, list1 and list2 are independent variables - they just happen to have the same values (references) at the moment. We could change the value of one of them, and it wouldn't affect the other:
list1 = null;
System.out.println(list2.size()); // Just prints 0
Now if instead of changing the variables, we make a change to the object that the variables' values refer to, that change will be visible via the other variable too:
list2.add("Foo");
System.out.println(list1.get(0)); // Prints Foo
So back to your original question - you never store actual objects in a map, list, array etc. You only ever store references. An object can only be garbage collected when there are no ways of "live" code reaching that object any more. So in this case:
List<String> list = new ArrayList<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("Foo", list);
list = null;
... the ArrayList object still can't be garbage collected, because the Map has an entry which refers to it.
To clear the variable
According to my knowledge,
If you are going to reuse the variable, then use
Object.clear();
If you are not going to reuse, then define
Object=null;
Note:
Compare to removeAll(), clear() is faster.
Please correct me, If I am wrong....
It depends on how many variables are referenciating to each of your objects, to explain this it would be better some code:
Object myAwesomeObject = new Object();
List<Object> myList = new ArrayList<Object>();
myList.add(myAwesomeObject);
myList = null; // Your object hasn't been claimed by the GC just yet, your variable "myAwesomeObject" is still refering to it
myAwesomeObject = null; // done, now your object is eligible for garbage collection.
So it doesn't depend whether you pass your ArrayList as an argument to a method or the like, it depends on how many variables are still refering to your objects.
If you passed an ArrayList to a method then list = null will have no effect if there is a live reference to the list somewhere eg in the calling code. If you call list.clear() anywhere in the code the references to the objects from this list will be nulled. Passing a reference to a method is not shallow copying it is passing reference by-value
Java GC automatically claims the objects when they are not referenced anywhere. So in most cases you will have to set the reference as null explicitly
As soon as the scope of the variable ends the object becomes eligible for GC and gets freed up if no other reference points to the object.
Java is pass by value so if you set the list as null in the method then it will not affect the original reference that was passed to you in the method.
public class A{
private List<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
A a = new A();
B b = new B();
b.method(a.list);
System.out.println(a.list.size()); //Will print 0 and not throw NullPointerException
}
}
class B{
public void method(List<Integer> list){
list = null;
//just this reference is set to null and not the original one
//so list of A will not be GCed
}
}
If you put the list into a hash map, the hash map now holds a reference to the list.
If you pass the list as an argument to a method, the method will have a reference to it for the duration of the method.
If you pass it to a thread to be manipulated, the thread will have a reference to the object until it terminates.
In all of these cases, if you set list = null, the references will still be maintained, but they will disappear after these references disappear.
If you simply clear the list, the references will still be valid, but will now point to a list that has suddenly been emptied, by means that may be unknown to the programmer and may be considered a bug, especially if you use the thread.
I was recently looking into freeing up memory occupied by java objects.
A piece of advice.
It is usually a bad idea to think about this. And it is usually a worse idea to try to "help". In 99.8% of cases, the Java garbage collector is able to do a better job of collecting the garbage if you actually just let it get on with it ... and don't waste your effort by assigning null to things. Indeed, the chances are that the fields you are nulling are in objects that are about to become unreachable anyway. And in that case, the GC is not even going to look at the fields that you've nulled.
If you take this (pragmatic) view, all your thinking about shallow versus deep copies and when it is safe to null things is moot.
There is a tiny percentage of cases where it is advisable to assign null ... to avoid medium or long term storage leaks. And if you are in one of those rare situations where it is "recycling" objects is actually a good idea, then nulling is also advisable.
Need some inputs:
Lets say i have N ArrayList and in each i am adding foo() object.
Foo foo = new Foo()
A.add(foo);
B.add(foo);
N.add(foo);
Now modification done on any one foo() object will reflect in all the other arraylist?
If YES WHY? and
whether this behaviour can also be achieved using any other collection like Vector etc...?
IF i make foo as null will it reflect in all arraylist?
Yes, because all lists only contain a reference to the same objects
Yes, all collections work like that
No, because you can only set a reference to null, and each list has a copy of the reference.
Any implementation of Collection API such as ArrayList or Vector hold reference to an object in heap memory so when you would get an index of a List by get(index) method, you achive reference to object so:
Yes, if get an index of list by get(index) method and then change the stat of the achieved object, changes stay in memory.
Yes,All Collection API have this behavior.
No,When achieve to a index of list, act is: "You achieve a copy of reference to object" and when set it to null, list instance don't any change.