Copying Array to another Array - java

im trying to copy the contents of one array to another without pointing to the same memory, but i cant.
My Code:
class cPrueba {
private float fvalor;
public float getFvalor() {
return fvalor;
}
public void setFvalor(float fvalor) {
this.fvalor = fvalor;
}
}
List<cPrueba> tListaPrueba = new ArrayList<cPrueba>();
List<cPrueba> tListaPrueba2 = new ArrayList<cPrueba>();
cPrueba tPrueba = new cPrueba();
tPrueba.setFvalor(50);
tListaPrueba.add(tPrueba);
tListaPrueba2.addAll(tListaPrueba);
tListaPrueba2.get(0).setFvalor(100);
System.out.println(tListaPrueba.get(0).getFvalor());
The result is "100.0" ....
Still pointing to the same object... Any short way to copy ? (without for(..){})
EDIT:
class cPrueba implements Cloneable {
private float fvalor;
public float getFvalor() {
return fvalor;
}
public void setFvalor(float fvalor) {
this.fvalor = fvalor;
}
public cPrueba clone() {
return this.clone();
}
}
List<cPrueba> tListaPrueba = new ArrayList<cPrueba>();
List<cPrueba> tListaPrueba2 = new ArrayList<cPrueba>();
cPrueba tPrueba = new cPrueba();
tPrueba.setFvalor(50);
tListaPrueba.add(tPrueba);
for ( cPrueba cp : tListaPrueba )
tListaPrueba2.add(cp);
tListaPrueba2.get(0).setFvalor(100);
System.out.println(tListaPrueba.get(0).getFvalor());
Still get 100...

There is no way to "deepcopy" an array, or any kind of Collection (which includes List) or even Map if your object itself does not have deep copy support (for instance, via a copy constructor).
So, to your question:
Any short way to copy ? (without for(..){})
the answer is no.
Of course, if your objects are immutable, this is not a concern.

Like dystroy said, you'll need to pass through the loop and clone all of the objects, like this:
List<cPrueba> newList = new ArrayList<cPrueba>();
for ( cPrueba cp : oldList )
newList.add(cp.clone());
And that's assuming your object implements Cloneable, or at least has a method called clone.
So no, there is no short way (unless you write your own static method), but it is possible.
EDIT
You need your clone method to return a new cPrueba:
public cPrueba clone() {
cPrueba c = new cPrueba();
c.setFvalor(this.getFvalor());
return c;
}
Also, make sure you call cp.clone() in your for loop; don't just pass cp to the add method. e.g., change
tListaPrueba2.add(cp);
to
tListaPrueba2.add(cp.clone());

vanilla Java can't do this for you.
but by adding some spice you can get it done with the Dozer framework:
http://dozer.sourceforge.net/

Related

How to create my own collection?

So lets say I have a class BaseballCard that creates a baseball card.
Now I need to make another class which would be my collection class.
For example I would call it BaseballCardCollection
and then I want to create methods like
size (which returns the numbers of cards in the collection)
addCard(adds a baseball object to the collection object)
removeCard (removes a baseball card)
and so on
What would be the best way to do this. I tried doing this
public CardCollectionList() {
BaseballCard[] baseballCardList = new BaseballCard[101];
}
So each object is insinuated with an array of type BaseballCard of size 100.
And then for example the size method I tried something like this
public int size(){
int size = 0;
for(int i = 1; i<this.baseballCardList.length; i++)
if (baseballCardList!= null)
size+=1;
}
But it doesn't work because "baseballCardList cannot be resolved to a variable"
You could try using ArrayLists - http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html:
ArrayList<baseballCard> baseballCardList = new ArrayList<baseballCard>(0);
public boolean addCard(baseballCard card){
return baseballCardList.add(card);
}
public boolean removeCard(int card){
return baseballCardList.remove(card);
}
public baseballCard getCard(int card){
return baseballCardList.get(card);
}
public int sizeBaseballCardList(){
return baseballCardList.size();
}
public ArrayList<baseballCard> getBaseballCardList(){
return baseballCardList;
}
Move the variable BaseballCard[] baseballCardList outside the constructor, make it a field in your class. Do similar with size.
This is how the class should look like:
public class CardCollectionList {
//fields
private BaseballCard[] baseballCardList;
private int size;
//constructor
public CardCollectionList() {
baseballCardList = new BaseballCard[101];
}
//method
public int getSize() {
return this.size;
}
}
You could try creating your own class implementing the Collection interface and define your own methods + implement Collection methods:
public class myContainer implements Collection <BaseballCard> {
}
You need to move the variable declaration from the constructor to the class, so you can access it in other methods, too.
class CardCollectionList {
BaseballCard[] baseballCardList;
public CardCollectionList() {
baseballCardList = new BaseballCard[101];
}
public int size(){
int size = 0;
for(int i = 1; i<this.baseballCardList.length; i++) {
if (baseballCardList[i] != null) {
size+=1;
}
}
return size;
}
}
The code is as close to your fragment as possible. There are several ways to improve this (keep track of the size when adding, automatic array reallocation etc.). But it is a start if you want to try this yourself.
Normally, you'd probably just use ArrayList<BaseballCard>.
Now I need to make another class which would be my collection class.
... What would be the best way to do this.
I don't have enough reputation to comment on your question, so I am going to assume that you just want to store BaseballCard objects in a Java Collection. The Java SDK offers a lot of options. Since you are asking about the "best" way to go then I would use one of those unless you need to add additional functionality .
if you don't find what you need from the Java SDK or just want to create your own Collection then follow the advice given by #michał-szydłowski above

How to get an array of vector<String> as return value in Java?

I want a method to return two vectors to the calling function. Here is what I tried:
static Vector<String>[] method()
{
Vector<String>[] toret = new Vector<String>[2]; // GETTING ERROR HERE
for(...)
{
toret[0].add(...);
toret[1].add(...);
}
return toret;
}
public static void main()
{
Vector<String>[] obtained = method();
}
Need help to remove that error.
Don't try to create arrays of generics. Try returning a List<Vector<String>> instead.
static List<Vector<String>> method()
{
List<Vector<String>> toret = new ArrayList<Vector<String>>();
toRet.add(new Vector<String>());
toRet.add(new Vector<String>());
for(...)
{
toret.get(0).add(...);
toret.get(1).add(...);
}
return toret;
}
I'd also suggest using List<String> (and List<List<String>>) instead of Vector<String> (and List<Vector<String>>) unless you absolutely need elsewhere the method-level synchronization that Vector provides.
You're doing 2 wrong things here:
Using Vector instead of List
Creating an array of parameterized type.
You can't create an array of concrete parameterized types. You have to go with a List<List<String>> rather.
instead of Vector[] toret = new Vector[2]; Use Vector toret = new Vector();
Also change like this
public static void main()
{
Vector obtained = method();
}
You can use 0 & 1 st index for your manipulations.
Vector is a dynamic array. so if you want to ensure capacity just give
Vector toret = new Vector(2)

How to deep clone a hash table

I have a project that I need to do very specifically and I need some help. I have looked basically everywhere for an answer and can't find it, not even on Stack Overflow. It has to do with cloning hashtables. (Both shallow and deep.)
I have pasted the code I have below, but in short, I have a class called EHashtable, which extends Hashtable. I then add some string keys and values of various custom class types. In the EHashtable class, there are methods called Clone() and dClone(). Clone() is supposed to create a shallow clone of its Hashtable - meaning the Hashtable is cloned but its values are not. dClone() is supposed to create a new Hashtable and clone each of the original hashtable's values to it (meaning each value points to different memory references than the first). It is also supposed to throw an exception if the custom made object is not cloneable.
Right now, even on a shallow clone (the Clone() method), changes one value in one Hashtable and will NOT change the value in the other. It seems as if each value is pointing to different references. I don't understand how to make the Clone() and dClone() methods do the two different things I want them to do. One other thing, the hashtable cannot have Generics. It needs to be Hashtable and not Hashtable<K, V>.
I have looked up how to for loop through a hashtable. That only works on an Object type, and Object types can't clone() due to the method's protected status. Below is my code, starting with the main method. I realize this is very specific, and all help is greatly appreciated.
import java.util.Hashtable;
import java.util.Iterator;
public class _Test {
public static void main(String[] arguments) {
Circle cr1 = new Circle(1);
Circle cr2 = new Circle(2);
Point po1 = new Point(10, 10);
Point po2 = new Point(20, 20);
PlaneCircle pcr1 = new PlaneCircle(po1, 11f);
PlaneCircle pcr2 = new PlaneCircle(po2, 12f);
EHashtable eh = new EHashtable(20);
eh.add(new String("C1"), cr1);
eh.add(new String("C2"), cr2);
eh.add(new String("PC1"), pcr1);
eh.add(new String("PC2"), pcr2);
try {
EHashtable ehCloned = (EHashtable) eh.Clone();
System.out.println("/***--Before Alteration--***/");
System.out.println("eh:");
System.out.println(eh);
System.out.println();
System.out.println("ehCloned:");
System.out.println(ehCloned);
System.out.println();
Circle cr3 = new Circle(99);
Point po3 = new Point(99, 99);
PlaneCircle pcr3 = new PlaneCircle(po3, 9999f);
eh.add(new String("C1"), cr3);
eh.add(new String("PC1"), pcr3);
System.out.println("/***--After Alteration--***/");
System.out.println("eh:");
System.out.println(eh);
System.out.println();
System.out.println("ehCloned:");
System.out.println(ehCloned);
System.out.println();
}
catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
catch (ClassCastException e) {
System.out.println(e.toString());
}
catch (Exception e) {
System.out.println("\nError Message:" + e.getMessage());
}
}
}
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
public class EHashtable extends Hashtable {
public EHashtable() {
}
public EHashtable(int capacity) {
}
// Done
public boolean add(Object key, Object value) {
if (!(containsKey(key) && containsValue(value))) {
put(key, value);
return true;
}
else {
return false;
}
}
// Done
public void Clear() {
clear();
}
// Done
public Object Clone() throws CloneNotSupportedException {
EHashtable eh = (EHashtable) this.clone();
return eh;
}
public Object dClone() {
EHashtable eh = new EHashtable();
for (Object key : keySet())
eh.put(key, get(key));
return eh;
}
// Done
public boolean isNotEmpty() {
return !isEmpty();
}
// Done
public Iterator iterate() {
return entrySet().iterator();
}
}
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public String toString() {
return "[x=" + x + ", y=" + y + "]";
}
}
public class PlaneCircle {
private Point p;
private float radius;
public PlaneCircle (Point p, float radius) {
this.p = p;
this.radius = radius;
}
public String toString() {
return "[p=" + p.toString() + ", radius=" + radius + "]";
}
}
public class Circle {
private float radius;
public Circle(float radius) {
this.radius = radius;
}
public String toString() {
return "[radius=" + radius + "]";
}
}
Simplest way is to serialize and deserialize the HashMap. However this requires to implement Serializable on all key and value classes. However wether its Cloneable or Serializable .. there is some work ´to be done in order to deep-copy object graphs anyway
Preferably with a fast serializer like http://code.google.com/p/fast-serialization/ :-). This way performance should be ok'ish
Found this in effective java
public class HashTable implements Cloneable {
private Entry[] buckets = ...;
private static class Entry {
final Object key;
Object value;
Entry next;
Entry(Object key, Object value, Entry next) {
this.key = key;
this.value = value;
this.next = next;
}
// Recursively copy the linked list headed by this Entry
Entry deepCopy() {
return new Entry(key, value,
next == null ? null : next.deepCopy());
}
}
#Override public HashTable clone() {
try {
HashTable result = (HashTable) super.clone();
result.buckets = new Entry[buckets.length];
for (int i = 0; i < buckets.length; i++)
if (buckets[i] != null)
result.buckets[i] = buckets[i].deepCopy();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
One more way to do is:
SerializationUtils.clone() serializes and de-serializes the entire object-graph referenced by the Map, that's why it takes so long. It creates a true deep-copy, however (provided you don't have funny serialization-stuff going on in your classes).
If all the elements are Serializable than serialize the hashMap and deserialize by ObjectInputStream , which will be a deep copy.
Please refer to this.
Some important point from this link:
Cloning through serialization
One solution to these problems is to clone using serialization.
Usually, serialization is used to send objects off somewhere (into a
file or over the network) so that somebody else can reconstruct them
later. But you can abuse it to reconstruct the object yourself
immediately. If the object is serializable at all, then the
reconstruction should be a faithful copy. In normal uses of
serialization, the original object is nowhere near; it could be on the
other side of the world at the far end of a network connection. So you
can be sure that changing the copy will have no effect on the
original.
Before going any further, I should caution that this technique is not
to be used lightly. First of all, serialization is hugely expensive.
It could easily be a hundred times more expensive than the clone()
method. Secondly, not all objects are serializable. Thirdly, making a
class serializable is tricky and not all classes can be relied on to
get it right. (You can assume that system classes are correct,
though.)
In addition to the Serialization ideas, if you have existing code to persist your Map to/from a file, a database, XML/json etc., that would be a "quick and dirty" option for you. Not quick performance wise, but quick to code.
Note that it is a poor idea to have methods which differ only by case (clear, Clear; clone, Clone). It isn't necessary because you can use the super keyword to call the superclass implementation of a method.
Hashtable itself is cloneable, so overriding clone is not necessary; the existing clone method already does what you need for a shallow clone, although for convenience you could override it to give a return type of EHashtable instead of Object:
public EHashtable clone() {
return (EHashtable)super.clone();
}
For a deep clone, you're right, since Object.clone is protected, you can't call it. It's a historical design mistake in Java. There are messy ways around it (serialization, or reflection, or defining an ActuallyCloneable interface that makes the method public) but I don't think you need to do these things, because (unless you left mutator methods out for brevity when pasting the question) all of the types that you're storing in your table seem to be immutable. There is no use in cloning them if they cannot change.
If they're not immutable in your real code, making them immutable is actually a very good idea for these simple value types. It enables you to simplify other code by not worrying about when you need to copy them.
Right now, even on a shallow clone (the Clone() method), changes one value in one Hashtable and will NOT change the value in the other.
You're not changing values; you're putting new ones. Changing values would be something like:
cr1.radius = 123;
That's not possible if your objects are immutable, but it would change the object as seen from both the original hashtable and from its shallow clone.
A couple of minor suggestions: (1) Printing the toString() of an exception will only print its name and message; the stacktrace information will be missing. To get the stacktrace too, use the printStackTrace() method. This also has the benefit of making sure it's printed to stderr instead of stdout (which may make it more visible; it's bright red in Eclipse). E.g.,
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
Or if there is nothing useful that can be done with a particular checked exception, it is better to simply rethrow it as an unchecked exception, so that surrounding code does not plow on in spite of errors:
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
(2) Doing eh.add(new String("C1"), cr1); (creating a new string) is a silly anti-pattern that has no benefits and adds unnecessary object creation and typing overhead. You can change it to just eh.add("C1", cr1);.

Java strange reference behaviour?

Lets say I have the following code:
public class Collection implements CollectionInterface{
ElementInterface[] elementArray = new ElementInterface[100];
int amountOfElements = 0;
public Collection()
{
}
public Collection(CollectionInterface collection)
{
CollectionInterface tempCollection = new Collection();
while(!collection.isEmpty())
{
ElementInterface element = collection.Remove().clone();
tempCollection.Add(element.clone2());
elementArray[amountOfElements++] = element;
}
collection = tempCollection;
}
public void Add(ElementInterface element){
elementArray[amountOfElements++] = element;
}
public ElementInterface Remove(){
ElementInterface element = elementArray[amountOfElements].clone2();
elementArray[amountOfElements] = null;
amountOfElements--;
return element;
}
public boolean isEmpty(){
return amountOfElements == 0;
}
public CollectionInterface clone()
{
return new Collection(this);
}
}
Allright, it might seem a bit strange, and it is. But if I use the following code:
CollectionInterface collection = new Collection();
collection.Add(new Element("Foo"));
collection.Add(new Element("Bar"));
CollectionInterface collection2 = collection.clone();
The first one doesn't contain any elements anymore. How is that possible?
It makes perfect sense. In the constructor, which is called by clone() with the original collection as an argument, you use:
ElementInterface element = collection.Remove().clone();
So you're removing elements from the original collection as you create the new one. You don't want to do that...
It's not really clear how you can achieve what you want, given that it looks like your CollectionInterface only has Add and Remove methods (which should be add and remove to follow Java naming conventions) to deal with elements - no way of accessing the collection non-destructively. That's very odd for a collection type. Is there any reason you're doing this in the first place instead of using the built-in collections?
EDIT: Ah - I've just had a thought. Within the class, you have access to the internals of the collection you're building... so you can destructively copy the elements from the collection you're given by calling Remove (as you are now) but then when you've built your array, you can use:
for (int i = 0; i < amountOfElements; i++)
{
collection.Add(elementArray[i].clone2());
}
... which will put the elemnts back again. This is horrible though...
You can not change the reference of an input parameter, as you try in the second constructor.
collection = tempCollection.
a) is this a syntax error,
b) collection is a local variable; assigning to it will change nothing on the outside of the constructor.
You can just implement the Clone method as follows:
public Object Clone() {
Collection rv = new Collection();
for (ElementInterface element : elementArray) {
rv.Add(element.clone());
}
return rv;
}
You could easily implement this in the constructor if necessary.

How do I create a instance of this Method here?

public LeNo generate (PrintStream stream) {
prepareOperands(stream);
LeNo l = (LeNo)left;
LeNo r = (LeNo)right;
if (l instanceof NumNo && r instanceof NumNo) {
return new NumNo((Integer.getInteger(l.name()).intValue()*Integer.getInteger(r.name())));
}
if ((l instanceof NumNo && l.name().equals("0"))||(r instanceof NumNo && r.name().equals("0"))) {
return new NumNo(0); // cut of rest of code here....
Is there a way I can create a new NumNo method without having to create it when I return?
The thing is I still want to return NumNo, but without creating a new NumNo doing it.
It is just return new NumNo(0); that you don't want to create right? Because it is the same every time? If so, you can create a static instance of that object. For example,
private static final NewNo ZERO = new NewNo(0);
This is called the flyweight pattern, where you create commonly used instances once.
return NumNo.getClass();
To return a class instead of an instance.
Create an instance with java.lang.Class.newInstance()
for example:
klass = generate(stream);
object = klass.newInstance();

Categories

Resources