ArrayList, java. Whats the difference between these two constructors - java

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.

Related

How can I create copy of a libgdx array with custom objects?

I have an array which contains values pawnArray. I need to find the highest value in pawnArray so using a custom class method getPawn() I retrieve the highest value but I do
public static Pawn getPawn(Array<Pawn> strollpawns) {
Array<Pawn> pawns = strollpawns;
pawns.sort();
Pawn best = pawns.get(0);
return best;
}
I hence need to copy the array since this method doesn't work. How can I make a copy of this array?
If your problem is with Java arrays (the syntax is Pawn[]) then you have methods in class java.util.Arrays for many different operations on them. What you are asking for could be accomplished with:
Pawn[] newArr = Arrays.copyOf(oldArr, oldArr.length);
Or, since array classes implement Cloneable, also with:
Pawn[] newArr = (Pawn[]) oldArr.clone(); // I don't remember if the cast is necessary
Note that both of these provide shallow copies, that is, the arrays are independent of each other (you can sort one and the indexes in the other are unaffected) but their contents are not.
EDIT: it has been kindly pointed out to me that your Array<T> is actually a class in libgdx. Looking at the documentation, then, you could simply use the constructor taking another instance of Array to create your shallow copy, since the doc says that the new instance will have the same type of backing array (not the same instance). For example:
Array<T> newArr = new Array<>(oldArr); // oldArr can be either Array<? extends T> or T[]
I'm adding a separate answer to this, since you want to copy your array and sort it in order to retrieve the highest value. My other answer deals with copying the array, while tjago's answer deals with sorting with a custom Comparator in order to customize what the "max value" is. However, it seems that the libgdx Array<T> class has a method to do just what you want, without having to make a sorted copy of the array.
This solution saves you code, memory and time if you only need one value from the sorted array: the minimum, maximum, whatever. If you need more than one, it is likely that sorting the array will be faster.
The method I'm talking about is Array.selectRanked, which returns the nth element according to the provided Comparator. There is another method selectRankedIndex which returns the index of that element instead of the object itself. You could use it like this:
// If Pawn implements Comparable<Pawn>:
Pawn minVal = arr.selectRanked(Comparator.naturalOrder(), 1);
Pawn maxVal = arr.selectRanked(Comparator.naturalOrder(), arr.size);
// If it does not implement Comparable, you need to provide a Comparator<Pawn>:
// Assuming Pawn has an "int getValue()" method that we want to compare:
Pawn minVal = arr.selectRanked(Comparator.comparingInt(Pawn::getValue), 1);
// You could also write your own implementation directly:
Comparator<Pawn> comp = (a,b) -> /* your int-returning logic here */;
Pawn minVal = arr.selectRanked(comp, 1);
It seems you have a java related problem. To help you with sorting In java object programming there exist concept of method overriding and interfaces.
Special interface for sorting is Comparator, you can either put him inline in method like this.
Collections.sort(pawns ,new Comparator<Student>(){
public int compare(Pawn1 p1,Pawn2 p2){
// Write your logic here.
//ie.:
return p1.score - p2.score;
//or for different order
return p2.score - p1.score;
}});
if this comparator return value == 0 means the value are equal;
if value < 0 means p1 is bigger than p2, therefore swap them.
Or put him inside your Object class like:
Class Pawn implements Comparator {
private String name;
private Position[][] posXY;
private int value;
....
Pawn() { ... }
...
public int compare(Pawn1 p1,Pawn2 p2){
return p1.value- p2.value;
}
}
then in your code you can call as you originally intended:
pawns.sort();
Pawn best = pawns.get(0);
and as expected you should get an maximum value Pawn from ArrayList.
The above code is just sample and requires tunning. But You should get an good overview now that Java has no idea how to sort Objects defined by a programmer unless he implements the Comparator logic for Collection sorting.
for external reference I suggest running a simple example on tutorialpoint
Answer to your question: How can I create copy of a libgdx array
Array<Pawn> pawns = new Array<Pawn>(strollpawns);
or if the pawns Array object already exists
pawns.clear();
pawns.addAll(strollpawns);
The first solution will create a new Array object that will be deleted on completion of the function, meaning time lost by garbage collector!
But I agree with Tenfour04: Duplicating an array and sorting it is a very expensive way to select the biggest value.

Check if an object of generic type is in LinkedList

I have a LinkedList of generic type State. In this LinkedList I have hundreds or even thousands of State objects. How can I, in the most efficient way to check if newly generated State object is already in the list?
State object:
public State(PlayerAddress player, LinkedList<BoxAddress> boxList, char[][] map, String solution, String stateHash) {
this.player = player;
this.boxList = boxList;
this.map = map;
this.solution = solution;
this.stateHash = stateHash;
boxListString = boxListToString(boxList);
mapString = mapString(map);
}
}
Additionally, State object consists of another generic objects as it is shown in the Constructor. How can I check if both State objects are the same in every aspect (PlayerAddress, LinkedList, etc.) ?
Have you tried the contains method? This could work. Also don't forget that you can overwrite stuff, so you could compare the hascodes as well by overwriting the hascode and compare methods.
In your case I would strongly suggest you will utilize the contains method. Which is the most efficient lookup for your case.
Looking at the java doc for contains:
public boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).
So you should only need to overwrite equals for your State class. The hashcode, will be required for sets.

Why Collections.copy still copies Reference, it doesn't clone the Objects that are copied?

Ok, I just want to copy List<String[]> list to List<String[]> list2. After that I will modify the object in list2 & I want that it won't affect any object int list.
String[] s={"1","2"};
List<String[]> list=new ArrayList<String[]>();
list.add(s);
List<String[]> list2=new ArrayList<String[]>(list);
Collections.copy(list2,list);
list2.get(0)[1]="3";
for (String[] strings : list) {
System.out.println(Arrays.toString(strings));
}
Out put: [1, 3]
Why we change things in list2 & it affect list1?
How to fix it?
Collections.copy() does not perform a deep copy.
It simply copies elements from one collection to another. It is basically the same as the ArrayList constructor, so you do not need to call both.
The first element in both list still refers to the same object. Thus, when you run your code, you are modifying the array in both lists. You can iterate over all your elements, and use Arrays.copyOf on each list item.
Something like this:
private List<String[]> deepCopy(List<String[]> list) {
List<String[]> copy = new ArrayList<String[]>(list.size());
for (String[] element : list) {
copy.add(Arrays.<String> copyOf(element, element.length));
}
return copy;
}
EDIT: Java < 1.6 version:
private List<String[]> deepCopy(List<String[]> list) {
List<String[]> copy = new ArrayList<String[]>(list.size());
for (String[] element : list) {
String[] elementCopy = new String[element.length];
System.arraycopy(element, 0, elementCopy, 0, element.length);
copy.add(elementCopy);
}
return copy;
}
What you are asking for is to copy the collection and clone all the objects it holds. In your case you only have lists of strings. The others already gave you good answers for that. Just as a note. In general it is not that easy, because there is no universal recipe for cloning objects. Because each object in the collection could have references to other objects itself. And those objects could have further references to more objects. So it depends on what you need.
Do you just need to clone the objects in the collection, but not the objects those objects reference to?
This is called "shallow copying".
Or do you need to copy all the objects down the objects reference tree. This is called "deep copying".
Or you might have requirements for something in between. Meaning you only need to copy certain objects.
You see there is no golden bullet which solves everything. That's why it is not implemented in a generic collection class. In some cases cloning might not even be possible if you are dealing with open file handles or other system resources.
But what you can do is, have your classes implement the Cloneable interface. Within the clone() method you can call super.clone() which does already a shallow cloning for you. Everything beyond that needs to be implemented by yourself. Then you only need to call clone() for each object in you collection in order to create the cloned objects.
This is how to implement Cloneable:
class MyClass implements Cloneable {
private int a;
private int b;
private MyClass c;
#Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Calling clone() would give you a copy of your MyClass-object. That means a and b would be copies as well as the reference to object c. But only the reference, not the object c itself. If you need that, you need to do something like this:
#Override
public Object clone() throws CloneNotSupportedException {
MyClass clone = (MyClass)super.clone();
clone.c = (MyClass2)c.clone();
return clone;
}
Here is a more detailed explanation for shallow and deep copying and the Cloneable interface:
http://javapapers.com/core-java/java-clone-shallow-copy-and-deep-copy/

How to move contents of one ArrayList to another?

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

A collection that represents a concatenation of two collections in Java

Is there a class that represents the concatenation of a collection with another collection? This class should be a Collection in itself, and should delegate all methods to the underlying (inner) collections - no extra memory should be allocated, nor any of the original collections modified.
Example usage:
Collection<String> foo = ...
Collection<String> bar = ...
// this should be O(1) memory and time
Collection<String> combined = concat(foo, bar);
if (combined.contains("Zee"))
...
for (String str : combined)
System.out.println(str);
As always for any collections stuff, look at google-collections. If you have Sets, specifically (not just a general collection), you want:
Set<String> combined = Sets.union(foo, bar);
which creates an unmodifiable view of the two sets. That is, changes in foo or bar will be reflected in combined (but combined.add() etc is not supported).
For the more generic case, you have Iterables.concat() but that merely lets you iterate over the joined item, the Iterable interface obviously doesn't include contains so you're a little hosed there.
The other collections utilities classes in google-collections (com.google.common.collect.Lists and com.google.common.collect.Collections2) don't contain any concatenation methods. Don't see why they couldn't, but at the moment they don't.
Your question is very vague. Especially "with another item another collection" is quite unclear.
You can at least add the contents of another Collection to the current Collection using Collection#addAll(). Here Collection can be anything of its subinterfaces/implementations, e.g. List or Set.
Example:
List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = Arrays.asList("bar1", "bar2", "bar3");
foos.addAll(bars); // Now foos contains everything.
Edit: Or do you actually want to create a new Collection based on an existing Collection and then add a new item to it? In this case just construct a new Collection with the existing Collection as constructor argument. E.g.:
List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = new ArrayList<String>(foos);
bars.add("bar"); // Now bars contains everything.
There is not, but writing it yourself should be straight forward
package ch.akuhn.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Concat {
public static <T> Iterable<T> all(final Iterable<T>... iterables) {
return new Iterable<T>() {
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Iterator<Iterable<T>> more = Arrays.asList(iterables).iterator();
Iterator<T> current = more.hasNext() ? more.next().iterator() : null;
#Override
public boolean hasNext() {
if (current == null) return false;
if (current.hasNext()) return true;
current = more.hasNext() ? more.next().iterator() : null;
return this.hasNext();
}
#Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
}
And then
for (Object each: Concat.all(collection,whatever,etcetera,...)) {
// ...
}
Just wrote this code here, compile at your own risk!
PS, if you gonna write unit tests for this class, send 'em to me.
I think what you're asking for is a Java construct that allows you to put collections together without modifying the original collections. In other words, you have collections A and B, both of size N and M respectively. After the concat call, you still have collections A and B and their sizes are still N and M, however you have collection C as well which points to A and B, making its size N+M.
The answer is no, Java doesn't have anything out of the box that does this... However you could write a quick wrapper that wraps a series of collections and add those collections to it. (All it would do is maintain references to each of the collections) and you could expose get/insert methods as needed.
Apache Commons Collections also has a more general CompositeCollection class which can be used as an interface to an arbitrary number of Collections.
I'm not sure what your asking. My interpretation of your question is that your looking for the add method on the Collection. I don't think that's what you're asking though.
Try InterleavingEnumeration or apache's commons collections' ListUtils (ListUtils.union())

Categories