Deep copy and returning an instance Java - java

So i am doing a first year university assignment question and i am going to be honest about it. I just want to make things clear before some of you come down-voting my question. I don't want complete code, i just want some help with a few things.
The question is divided into two parts. The first part is to write a Nucleotide class whose constructor has two properties. A single character called base that has to be either 'a' or 'c' or 'g' or 't' otherwise it should be 'n' and a boolean called degenerate.
My code for this part is here:
class Nucleotide {
private char base;
private boolean degenerate;
public nucleotide(char base, boolean degenerate){
if(base != ‘a’ || base != ‘c’ || base != ‘g’ || base != ’t’){
this.base = ’n’;
} else {
this.base = base;
}
this.degenerate = degenerate;
}
}
The next part of the question says to use the Nucleotide object and create a new Bacteria class. An instance of bacteria consists of a genome (a collection of nucleotides), and a species (a String).
You must create a constructor which accepts a String and a collection, and uses those to
initialize the species and the collection of nucleotides.
My code for this part is here:
class Bacteria {
//private ArrayList<Nucleotide> genome;
private String species;
public Bacteria(String species, ArrayList<Nucleotide> genome) {
genome = new ArrayList<Nucleotide>();
this.species = species;
}
My problem starts with the next step which asks us to write an instance method that performs deep copy and returns an instance of Bacteria.
public Bacteria binaryFission() {
How can i perform deep copy without serialization and reflection. I hardly know anything about those things.
Again i need pointers or the basic idea of how to go about completing the binaryFission() method. I have gone through several deep copy questions that are on SO but none of them are relevant to my question so i don't believe that i am asking a duplicate question. I am happy to provide more details though.

This is the way to do it manually
public Bacteria binaryFission() {
String speciesClone = this.species;
ArrayList<Nucleotide> genomeClone = new ArrayList<Nucleotide>();
//now iterate over the existing arraylist and clone each Nucleotide
for(int index = 0; index < this.genome.size(); index++)
{
genomeClone.add(new Nucleotide(
genome.get(index).getBase(), //needs to be added to the Nucleotide class to retrieve the base variable
genome.get(index).getDegenerate() //needs to be added to be allowed to get its degenerate
));
}
return new Bacteria(speciesClone, genomeClone);
}
FYI - you'll need to add getters for your Nucleotide class private variables in order for this to work since they are private and Bacteria won't have access to their values without them.

Since Nucleotide has no setters, and its fields are primitive, it is effectively immutable (can't be changed and therefore safe to "reuse"). You would be better to make the fields final to formally make it immutable.
All you need to make a deep copy is to make a shallow copy of your Nucleotide list and use that in your new Bacteria. You can make a copy like this:
List<Nucleotide> copy = new ArrayList<>(genome);
You could create a simple factory method on Bacteria that returns a deep copy of itself:
public Bacteria copy() {
return new Bacteria(species, new ArrayList<>(genome));
}

Related

Do immutable types need copy constructors?

Say I have an immutable DecimalNumber class:
public final class DecimalNumber {
public final String str;
public DecimalNumber(String str) { this.str = str; }
public DecimalNumber(DecimalNumber copy) { this(copy.str); }
public boolean isZero() {...}
public DecimalNumber add(DecimalNumber other) {...}
...
}
and I decide to implement add like this:
public DecimalNumber add(DecimalNumber other) {
if (other.isZero())
return /* the same object */
...
}
Should I return this (less memory use) or a copied object new DecimalNumber(this)?
I would think simply returning this should be fine but is there ever a benefit to or reason for creating a new object or is it ever preferred?
If a class is immutable and final, then you can return this.
If it is not final, you cannot be sure that the this instance is really immutable. You might actually be dealing with a subclass which adds mutable state.
Note that a class is only really immutable if:
All its fields are final, even the private ones. (Because of the Java memory model allowing other threads to see unfinished/default values for non-final fields, a non-final field with only a getter does not suffice.)
All its fields are either of immutable classes themselves, or access to them is restricted so that you can be sure they will never be changed.
In your case these two conditions are met, since String is an immutable class. If you known that no subclasses of your class exist, then you can (in fact, should IMHO) return this. To make sure that no subclasses of your class can exist, you can make it final.
As you object is immutable, we need to create another copy whenever we change it. But here, adding zero will not change the value of the object.
Hence, we can return the same object.
Consider the concat() code from String.java for reference:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
As you can see, there is no harm in returning the same object.
why do you feel strange about returning this?
If you would return a new object you would not need the if in the first place, so returning new DecimalNumber(this) is no option at all!
There is no need to ever make a copy of an immutable value object. Since it's immutable, both the original and copy will be equivalent for all time, and thus having two copies is nonsensical.
Not only would I return this in your example, I would go one step further and completely delete your copy constructor.
As an example, the Java String class actually has a copy constructor. But all that this is done is led to code by inexperienced developers who either don't realize it's immutable (or don't understand what that implies), so they do new String(aString) or new String("Hello"), which does nothing but waste memory and processor cycles.
I would return this, if an object is really immutable. You simply do not need two instances that will be surely always equal.
https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

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.

Array reference type in a method

I have been given a starting code to work on a project, however I am confused about the following code and cant seem to find any examples online!
public static Entity[][] read(){ ... }
How can I handle this Entity to add new entries to an array, and then how can I return this?
The following constructor is invoked by a different class.
public World() {
aWorld = new Entity[SIZE][SIZE];
int r;
int c;
for (r = 0; r < SIZE; r++) {
for (c = 0; c < SIZE; c++) {
aWorld[r][c] = null;
}
}
aWorld = FileInitialization.read();
}
I feel it would be much simpler if the array was just a parameter or if it were something like:
public static int[][] read(){ ... }
UPDATE:
The goal is to read from a file in the method read() and then assign the an entity to the correct location based on the location in the file. But I am not able to assign since the data types would be incompatible, Required is Entity, but I want to be able to set it to an int, char or String.
To add to an array of objects, you do exactly what you would with an array of primitives (e.g. ints), you just use Entitys. So if you want to add something to aWorld you use
aWorld[r][c] = new Entity(...); //with provided constructor's parameters
// or
aWorld[r][c] = existing_Entity; //for an Entity variable you already have
When you're done adding, you simply return the array aWorld.
If FileInitialization's static read() is going to return Entity[][], that's an entity array by itself. It means that you shouldn't iterate aWorld, rather assign the return value to it directly like
aWorld = FileInitialization.read();
Inside the read(), use that for loop you've made in the constructor and add a new Entity object as noted by Linus
Alright I would like to say thanks to all of you here as I was set on the right direction. But I would like to share my answer which should be simple and hopefully make someones life easier in the future.
To initialize the array of objects just do it as you would initialize any other array, in this case:
Entity[][] reference_name = new Entity[SIZE][SIZE];
To return this value, simply return the reference:
return reference_name;
Now the part where you actually modify an entry into your array.
Lets say you have something like
public static void Entity[][] read() { .. }
you need to create a class file Entity.java (same name as the array type being passed)
In this case it would look something like this:
public class Entity {
private char appearance;
public Entity(char anAppearance) {
appearance = anAppearance;
}
now to give this array an entry do something like this:
reference_name[0][0] = new Entity('X');
alright and in case you are wondering how to display this just add an accesor method to class Entity.
public char getAppearance() {
return(appearance);
}
and to output:
System.out.println(reference_name[0][0].getAppearance(); );

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.

How to create an equals method that compares two object arrays of a class?

I am trying to create a equals method that compares two objects. The thing is, I'm a bit a of new to this stuff so I'll try to explain my goal as easy as possible.
public class A {
...
}
public class B {
private A[] arr = new A[10];
public boolean equals(A[] temp) {
//compare
}
}
Assume the code above is a summary of what I have. Now, assume I had: arr.equals(Obj)
Obj being another A[] object. Now in my equals statement, I want to reference the original arr array, how do I go about doing that?
For example, let's say I wanted to compare arr's length to temp's length (aka Obj's length), how would I do that? I know it would be something like (temp.length == arr.length) but how do I access arr when I pass it through by doing arr.equals(obj)?
EDIT: Just to clarify, assume the objects aren't simple arrays. So for instance, class A could have a Name, a Type (Both Strings) and possibly a Quantity (an int), so I wouldn't be able to simply compare them like they're two normal arrays.
Thanks!
You can use java.util.Arrays.equals(Object[] a, Object[] a2) which tests if the two specified arrays of Objects are equal to one another
Use the keyword this, which always represents the object you are applying the method to (immediately before the dot). For example:
public boolean equals(A[] temp) {
return this.length == temp.length ;
}
Now, in the particular case of your code, you are not defining method equals as part of class A, but of a class B whose instances contain arr. Then, the solution would be:
public boolean equals(A[] temp) {
return this.arr.length == temp.length ;
}
Write a equals mwthod in your class A
public class A {
...
//Override equals method.
}
Now if you want to compare 2 arrays of class A you can simply use java.utils.Arrays.equals(A a1[], A a2[]);
You have to override equals method in class A coz java.utils.Arrays.equals internally uses class A's equals.
Here is an example, go through it.

Categories