Memory reputation management

I introduce recursion in Java with a large ArrayList. At one stage of the recursion, I split this list into two lists half of each size and apply the same method recursively to both lists. However, since I no longer need a large list after splitting it, I would like to remove it from memory. Some time after the search, I came up with the following:

public some_object recursiveMethod(ArrayList large_List) { //Compute the two sublists ArrayList lower_half = lowerHalf(large_List); ArrayList upper_half = upperHalf(large_List); //Delete large list from memory large_List = null; //Recursively call on smaller lists return procedure(recursiveMethod(lower_half),recursiveMethod(upper_half)); } 

Will this work, i.e. Will GC delete a large list?

+6
source share
4 answers

It seems to divide and rule . In such cases, it is better to avoid local (hard) links (parameters and time parameters) and GC overheads in aggregate, keeping this large list along with easy subscription views using List.subList () (wrappers, links to a large support list) or simple pair of indices.

If these sublists must be changed independently of the source list, you can duplicate this large list once before introducing recursive processing, which should be more efficient than several independent copies of the subscriptions.

 public some_object recursiveMethod(List large_List) { //Create views of the two sublists List lower_half = large_List.subList(0,large_List.size()/2); List upper_half = large_List.subList(large_List.size()/2,large_List.size()); //Recursively call on list views return procedure(recursiveMethod(lower_half),recursiveMethod(upper_half)); } public some_object recursiveMethod2(ArrayList large_List, int begin, int end) { //Create views of the two sublists int size = end - begin; int lowerBegin = begin; int lowerEnd = begin + size/2; //exclusive int upperBegin = lowerEnd; int upperEnd = begin + size; //exclusive //Recursively call on list views return procedure(recursiveMethod2(large_List,lowerBegin,lowerEnd),recursiveMethod2(large_List,upperBegin,upperEnd)); } 
+1
source

This will not work, because lower_half and upper_class still refer to the list in the caller, which does not cancel them until it finishes.

For example, take the first actual parameter procedure : recursiveMethod(lower_half) . lower_half link is copied to the actual parameter called by recursiveMethod large_List . So you have the same list:

  • Caller reference as lower_half .
  • And within the current call as large_List

In your current call, the large_List reference is large_List , but not the lower_half . So the list is still mentioned somewhere and therefore is not compiled by the GC.

+2
source

GC will delete all objects without a link. However, this does NOT work with all JVMs. I'm not 100 percent if you have a JVM with GC.

+2
source

Why drop the old array and create two smaller ones? Maybe you can save the array and just make a "virtual" partition?

lowerHalf will return an object that writes the beginning and end of the index to the array as your new virtual array.

That way you can split the array without shuffling around the content ...

 public some_object recursiveMethod(ArrayList large_List, int start, int end) { //Compute the two sublists StartEndIndexObj lower_half = lowerHalf(large_List); StartEndIndexObj upper_half = upperHalf(large_List); //Recursively call on smaller lists return procedure(recursiveMethod(large_List, lower_half.start, lower_half.end), recursiveMethod(large_List, upper_half.start, upper_half.end)); } 

Also see Sam's answer for the version with List.subList.

+1
source

Source: https://habr.com/ru/post/970078/


All Articles