How to move contents of one ArrayList to another? - java

Is there a way to move the entire contents of an ArrayList to another instance of ArrayList in O(1)?
I.e.: only the reference to the backing array is passed from one instance to the other (elements are not copied one by one).
For example:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = new ArrayList<>();
a.moveContentsTo(b);
// 'a' is now empty, while 'b' contains everything that 'a' did before and 'a != b'
// It is desired that the 'moveContentsTo' method is O(1)
Even better, is there an ArrayList#swapContents(ArrayList) method?
Further explanation and use-case:
Further explanation 1: the references of 'a' and 'b' must not be exchanged. I am not looking for tmp = a; a = b; b = tmp; type of solutions.
Further explanation 2: The operation must be ~O(1) in time.
The use-case: This is useful when an object wants to encapsulate a list constructed outside:
public class A {
private ArrayList<String> items = new ArrayList<>();
/**
* This method takes the sole ownership of the contents. Whoever
* passed the list from the outside will not be able to modify
* contents of 'this.items' from outside the class.
*/
public AnImmutableObject(ArrayList<String> items) {
if (items != null) {
items.moveContentsTo(this.items);
}
}
/**
* Other collections that do not provide the 'move' functionality
* must be copied. If we just stored the reference to 'items' we
* would break encapsulation as whoever called the constructor
* still have write capabilities to the collection.
*/
public A(Collection<String> items) {
if (items != null) {
this.items.addAll(items);
}
}
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
}
Notice that we want to avoid making a copy (to increase speed and decrease memory usage). The crucial bit is that the callee must lose the ability to modify the (now encapsulated) ArrayList.

#Lirik answer is greate +1. However, if you are looking for a real ArrayList#swapContents(ArrayList), here is how you can do it:
public static void swapContents(ArrayList<String> listA, ArrayList<String> listB)
{
List<String> temp = new ArrayList<String>(listA);
listA.clear();
listA.addAll(listB);
listB.clear();
listB.addAll(temp);
}

AFAIK, it's very not Java-like to keep track of "ownership" of references (at least on the programmer's side) which is why I doubt that you'll find the std::move()-like functionality that you want. It just isn't very commonly needed in Java.
I guess C++ needs to keep track of object ownership explicitly because there is no garbage collection.
I think that your best bet is to create a defensive copy in your constructor and save space by relying on copy constructors of immutable objects:
public class AnImmutableObject {
private final List<String> items;
/**
* Creates a new immutable object with the given list of items.
* Always deep copy from an outside source, because we can't know if the
* calling code will modify that collection later.
*/
public AnImmutableObject(Collection<String> items) {
// It's a constructor. We know items needs to be set.
// We are creating a new array list, using its constructor which deep
// copies the collection, and immediately wrapping it to make it truly
// immutable. We are guaranteed that no one will hold a reference to the
// mutable view of the new ArrayList.
this.items = Collections.unmodifiableList(new ArrayList<String>(items));
}
/**
* Creates a new immutable object with the same items as another.
* Copying the reference here is completely safe because we
* enforce the immutability of the items array.
*/
public AnImmutableObject(AnImmutableObject source) {
items = source.items;
}
public List<String> getItems() {
return items;
}
}
At this point, you can "pass the arrays around" (really share them) in O(1) between your own immutable objects:
ImmutableObject a = new ImmutableObject(Arrays.asList("A", "B", "C")); // O(n)
ImmutableObject b = new ImmutableObject(a); // O(1)
Hopefully, something like this can suit your purposes.
Another route you could go is use Guava's ImmutableList. Since these are immutable, you can safely copy the reference to the ImmutableList in a constructor.
The main approach is about making it safe for you to copy references to the lists rather than taking ownership over them.

This should do it:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = a;
a = new ArrayList<>();
Conceptually speaking, a is now empty and b contains what a contained before. There was a single assignment and no copying of data, which is about the fastest you can do it. Does that satisfy your requirement, or do you actually want a to still reference the same array except that the given array should now be empty?
Update
I don't believe that in C++ the time complexity for the move operation is O(1) either. It's also prudent to point out that "because classes in Java use reference semantics, there are never any implicit copies of objects in those languages. The problem move semantics solve does not and has never existed in Java." (see the answer by FredOverflow: C++ Rvalue references and move semantics)
Is there a way to move the entire contents of an ArrayList to another ArrayList so that only the reference to the backing array is passed from one to the other (i.e., so that elements are not copied one by one).
Given the above statement, then if you copy something from array a to array b in Java, both arrays will reference the same data. All that you do with move semantics in C++ is that you save the temporary object which needs to be created in order to make such a copy:
X foo();
X x;
// perhaps use x in various ways
x = foo();
The last one does:
destructs the resource held by x,
clones the resource from the temporary returned by foo,
destructs the temporary and thereby releases its resource.
Move semantics does:
swap resource pointers (handles) between x and the temporary,
temporary's destructor destruct x's original resource.
You save one destruct, but only in C++... the above problem does not exist in Java! See this article for more details on move semantics: http://thbecker.net/articles/rvalue_references/section_02.html

Related

How does the method assigns the array?

I am confused about how the array was assigned to any data, as the method meant to be a self contain
or I haven't understood a fundamental concept
// Craft stall stock and till program
import java.util.Scanner;
public class revisonTest {
public static void main(String[] args) // where program exicutes
{
final int numOFitems = 50;
String[] item = new String[numOFitems];
int [] broughtItem = new int[numOFitems];
int[] costItem = new int[numOFitems];
int COUNT = getDetail(item,broughtItem,costItem);
System.out.println(item[0]);
}
public static int getDetail(String[] name,int[] quantities,int[]cost)
{
int count =1;
int arrayIndex =0;
String answer = "";
while(!(answer.equals("Exit")))
{
answer = userInput("Item"+count+": ");
if(!(answer.equals("Exit")))
{
name[arrayIndex] = answer;
quantities[arrayIndex] = Integer.parseInt(userInput("How many "+name[arrayIndex]+" have you brought? "));
cost[arrayIndex] = Integer.parseInt(userInput("How much does a "+name[arrayIndex]+" cost? "));
count++;
arrayIndex++;
}
}
return count;
}
public static String userInput(String question)
{
Scanner sc = new Scanner(System.in);
System.out.println(question);
return sc.nextLine();
}
}
String[] item = new String[numOFitems];
This first makes a new treasure map named 'item'.
This makes a new treasurechest capable of containing numOFitems treasuremaps, and buries it in the sand. It is then filled with that many blank maps that lead to no treasure.
This updates your item treasuremap to point at this treasurechest-containing-maps.
getDetail(item,broughtItem,costItem);
This takes your treasuremap to the treasure-of-maps and makes a copy of it, and then hands the copy to the getDetail method. Your copy is unmodified and cannot be modified by getDetail... but that's just your copy of the treasure MAP, not the treasure. Note that getDetail calls this copy name and not item - which it is free to do.
(in getDetail) name[arrayIndex] = answer;
This is getDetail taking its name treasuremap (which is a copy of main's item map), follows the map, gets a shovel out, digs down, finds the treasure, opens it, finds the arrayIndexth map in it, pulls it up, and copies its answer map onto it.
Thus.. when main follows its copy of its map to the same treasure, same thing happens.
Of course, in java we use different jargon.
'treasure' -> 'object'
'treasuremap' -> 'reference'
'follow the map, dig down, open treasure' -> 'dereference'.
'create treasure' -> 'instantiate an object'
There are two different concepts here:
Allocating an array and assigning an array reference to a variable, and
Assigning values to elements in the array
In main, the new operation creates an array of a certain size, and assigns a reference to that array to the variable named item.
The call of getDetail(item,...) makes a copy of that reference (not the array itself) available to the method. Inside getDetail, this reference is stored in what is effectively a local variable, named name.
The loop inside getDetail is collecting answers (which are actually String references) and storing them in successive elements of the array that it knows as name and which the caller knows as item.
name[arrayIndex] = answer;
(Similarly for the other two arrays, of course)
In summary, getDetail is provided with an existing array, into which it writes values.
Incidentally, if the user types too many answers (more than name.length) you'll run off the end of the array, and get an 'index out of bounds' exception.
A String in java is considered a non-primitive data type. So when you created your item array using:
String[] item = new String[numOFitems];
You actually created an empty array of String objects. Based on your code the array has 50 empty spaces where you can store data.
The next part of your code is designed to get input from the user and fill those arrays:
int COUNT = getDetail(item,broughtItem,costItem);
Note: getDetail() never returns the item[] array, so how do you access the data?
When you pass your item array as an argument to the getDetail() method, you are actually passing that array as a reference.
In Java, non-primitive data types are passed as reference. This means that instead of sending the data to the getDetail() method, your actually sending information about where the data is located in memory.
Within your getDetail() method you can manipulate the data and the changes will be reflected on the original array without having to return it.
That is the reason why your print statement shows data in the array:
System.out.println(item[0]);
Any changes made within the getDetail() method, to the array, automatically appear on the original data source.

where stored values from constructor in java ?

I always use constuctor only for attributes of one object.
But i thin when i wrote this :
public Predmet(int esp,int obaveze,int cena){
this.cena=cena;
this.obaveze=obaveze;
this.esp=esp;
List j = new ArrayList();
j.add(8);
this.nesto=(int) j.get(0);
}
where are stored this ArrayList,does it part of object,or is on stack and have reference to array in heap?
The ArrayList is created on the heap and only referenced by the local variable j from the stack here. After the execution of the constructor it will be eligible for garbage collection.
Constructor is working very similar the way methods work. At runtime, anything you define inside constructor/method are called local variables. Their scope will end as soon as execution hits the end of the constructor/method. After consturctor, your list will be eligible for GC. However, this.nesto will still get value 8 as its primitive type.
First, please don't use single variable names! This is bad practice and makes files harder to read. Using a more descriptive name helps to promote code readability.
The way that List j is created, it only exists in the scope of the constructor. After your constructor, List j is no longer accessible. If you wanted it to be accessible after the constructor, have a field for the object. For example:
public class Example {
private int specialNumber;
private List<Integer> numberList;
/**
* Constructs a new Example Object
*/
public Example(int exampleNum){
// specialNumber can be accessed from a Getter method (getSpecialNumber)
this.specialNumber = exampleNum;
this.numberList = new ArrayList<Integer>();
this.numberList.add(exampleNum);
// numberList is a field of this Example now
List<Integer> disappearingList = new ArrayList<Integer>();
disappearingList.add(exampleNum);
// After this method finishes, disappearingList will be gone
}
// disappearingList is no longer accessible
/**
* Gets this Example's specialNumber value
* #return int this.specialNumber
*/
public int getSpecialNumber(){
return this.specialNumber;
}
/**
* Gets this Example's numberList
* #return List<Integer> this.numberList
*/
public List<Integer> getNumberList(){
return this.numberList;
}
}
There is probably a way to hook into some of the Java cleaning methods and pull it out, but that will get a little messy. If you want to be able to create an Object inside another Object, and use it after the constructor, it must be saved as a field.

ArrayList, java. Whats the difference between these two constructors

I'm kind of a newbie still in java, can you tell me whats the difference between these two constructors?
First:
public class Plan
{
ArrayList<Point2D> points;
public Plan(ArrayList<Ponto2D> points)
{
this.points = new Arraylist<Point2D>(points);
}
}
and this :
second:
public class Plan
{
public Plan(ArrayList<Point2D> lpoints)
{
points = new ArrayList<Point2D>();
for(Point2D p : lpoints) point.add(p.clone());
}
}
The first constructor is a shallow copy, the second one a deep copy.
Answer given by S.Lott for this question.
Shallow copies duplicate as little as possible. A shallow copy of a
collection is a copy of the collection structure, not the elements.
With a shallow copy, two collections now share the individual
elements.
Deep copies duplicate everything. A deep copy of a collection is two
collections with all of the elements in the original collection
duplicated.
this.points = new Arraylist<Point2D>(points);
This takes a whole collection and uses the collection to initlaize your points ArrayList.
for(Point2D p : lpoints) point.add(p.clone());
That has the same result but adds each element of the lpoints-collection one by one to your points list.
So for your usage, use the first possibility.
in first case, the parameter ArrayList share the same points (p1.equals(p2) would be true, p1 == p2 would be true)
in the second case, they have different copy of the points (p1.equals(p2) would be true, but p1 == p2 would be false)
In your first constructor you use the default Java Constructor for creating an ArrayList that takes a collection as it's argument.
(From Java Docs)
public ArrayList(Collection < ? extends E > c)
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.
This is basically same as writing your own iterator (From your example).
public Plan(ArrayList<Point2D> lpoints) {
points = new ArrayList<Point2D>();
for(Point2D p : lpoints)
point.add(p.clone());
}
In this example however we use a method called .clone() because we don't want each object's shallow copy. We want to duplicate them.
[Edit]: Both the examples don't do the same thing. First one is a shallow copy and second one a deep copy.

Is it necessary to deep copy an array in java?

As far as I know and researched, arrays in Java are not objects but they're reference-types. My doubt is, when I want to return an array should I return a deep copy (like you would do with an object) with a clone() method for example, or can I return the variable countaining the array like it was a simple-type variable (ie. int or double) with a get method? For clarification porpuses, I will insert an example code to expose this situation:
public class List
{
// Instance Variables ----------
private int[] list1;
private int[] list2;
// Constructors ----------
public List()
{
list1 = new int[0]; list2 = new int[0];
}
public List(List x)
{
list1 = x.getList1();
list2 = x.getList2();
}
// Get methods
public int[] getList1()
{
return list1;
}
public int[] getList2()
{
return list2;
}
// Set methods
public void setList1(int size)
{
list1 = new int[size];
}
public void setList2(int size)
{
list2 = new int[size];
}
// Compare reference between an array and the instance variables
public boolean equals (int[] x)
{
if ( x == list1 || x == list2)
return true;
else
return false;
}
}
And now I have a TestClass the uses class List like this:
List listx = new List();
int[] listy = listx.getList2();
boolean test = listx.equals(listy);
System.out.printf("Result: " + test );
With this said, when I use the method equals to see if the two arrays share the same reference or adress, I get always the result true!! Am I breaking OOP basic principals with this? Will I loose control because listy is pointing to listx instance variable?
Well, I'm really confused with this and I don't know if this is right(being array a non-instantiable class) or If I should send some kind of deepcopy insted of shallow using a Clone method in other to ensure that all basic OOP principals are fulfilled, and with this principals I mean that the class method should be acessed only by the API and that the internal state(instance variables) can only be acessed by the class itself.
You are not breaking OOP principals. However, you are breaking principals of functional programming. Functional programming views leaking of access as losing of control.
Whether or not you want to practice functional programming is up to you, Java doesn't take a stance in that matter.
You may want to consider if it's important not to leak access for this particular class. If you find it important not to leak access then make this class immutable.
You can also guard the instance variables. In this scenario any possible changes to the variables must be handled by the instance class. However, the instance could be modified from separate contexts and result in loss of control. For this reason functional programming only allows immutable classes.
If you want the invoker of the method to be able to modify the original array, you don't need to do a copy. Otherwise, you do.
Check your implementation of equals(). It should be reflexive, symmetric, and transitive, which is not the case on yours.
It depends on your use-case if you want to deep copy or not. If your elements are immutable you normally not need to do a deep copy. If they can change, it depends if you want to see the changes in your receiver of the copy or not. Typically when you want a snapshot of the given data you will have to deep copy it. However keep in mind that Arrays are most of the time not a good argument or return type for APIs anyway.

Immutable Class how to tell

I understand that immutable means that it is an object that will not change state after it is instantiated. But in this line of code I dont see Final when the array values is declared.
Is this class immutable? Can anyone explain how to find out. Thanks
public class A {
private double[] values;
public double[] getValues(){
return values;
}
}
As other have written this object is considered to be mutable in its state. What it is immutable to is that you can not exchange the array it holds. But you can change the array's content (getValues()[0] = 10;).
To convert this to a immutable object you must use List instead of an array. With List you can use Collections' method unmodifiableList to convert a given list into a version you can savely expose to the outside. If the caller of getValues() uses add or remove on a unmodifiable list it will result into a UnsupportedOpertionException keeping your object save from being modified.
If you need to stick to arrays you need to provide a copy (System.arraycopy) or a clone (clone()) of the array.
Usually a object is considered to be immutable if you can not change its properties (including inherited properties from superclasses. This usually includes the properties values as well but this is a blurred definition.
For example if you have a class that holds a File instance which points to document file and this File instance can not be changed the class is considered to be immutable (the inforamtion it provides never changes) but the document it points to can be mutated and changed every time. So its a blurred line actually (remember in your example you can not change the array but the content of the array).
Yes the code pasted is not having any final keyword associated and has no immutable behavior.
Well i would like to bring forth some key guidelines related to writing immutable classes in java :
1.) Ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
2.) Make fields private and final
force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention)
3.) Do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
4.) If the class has any mutable object fields, then they must be defensively copied when they pass between the class and its caller
A a = new A();
a.getValues()[0] = 1.2;
This would work as long as values is not empty. You will however not be able to reassign values to a new array. That is: a.getValues() = new double[5]; will not work.
The class is not immutable, as I can change values, just not reassign it.
Here is a simple verification. the values are initialized to 1,2.
Using the getter and a reference, one is able to change the values inside the first item in the array after the object is created
public class A {
private double[] values;
public double[] getValues() {
return values;
}
public static void main(String[] args) {
A test = new A();
test.values= new double[]{1, 2};
double[] valuesref = test.getValues();
valuesref[0] = 10;
for (int i = 0; i < test.values.length; i++) {
System.out.println(test.values[i]);
}
}
}
This can be avoided if getValues() returns a copy of the array.

Categories