My question contains 2 subquestions, therefore it is not limited to java but takes programming paradigms in general into consideration.
I need a Loop which does a usual "forEach" but also provides for each index its previous runs. Let me elaborate.
Let's define:
OBJECTS = a collection of X, where X is just any Type of Object/Data
PREV = the results of the previous iterations as a Collection of Y, Y beeing the result of a single iteration of an X
what "my" suplementalForEach would do is:
OBJECTS.supplementalForEach((PREV, OBJ) -> doStuff(PREV, OBJ))
or as non-stream variant
var PREV = new ArrayList<>();
for(var OBJ : OBJECTS) {
var result = doStuff(PREV, OBJ);
PREV.add(result);
}
So in essence in Java this would be a forEach, taking a BiFunction<R, T> instead of Consumer<T>
The Question now is, is there already a programming concept to this idea? If yes, what is it called? And if yes, is there a Java Implementation?
If no i can just implement it myself but this is a curious question of mine. Btw i didn't find anything yet on Google and Stackoverflow to this.
EDIT2:
as of now i have implemented these methods, feel free to use them as you please (Keep the comments and references)
/**
* #author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* <pre>
* Cumulative Iteration:
* the process of iterating with the results of the previous iterations
*
* definition:
* D domain (collection of X)
* X ∈ of domain, Data/Object/Value
* R results of previous iterations (List<Y>)
*
* f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
*
*
* for X ∈ D {
* R.add(R, X)
* }
*
* ORDER sensible! use ordered Collections such as Lists and so on.
* </pre>
* #param <X>
* #param <Y>
* #param col
* #param loopIteration
*/
public static <X, Y, LIST extends List<Y>> void cumulativeIteration(final Collection<X> col, final BiFunction<List<Y>, X, Y> loopIteration, Class<Y> clazz) {
final ArrayList<Y> previous = new ArrayList<>();
col.forEach(x -> previous.add(loopIteration.apply(previous, x)));
}
/**
* #author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* Same as {#link Essentials#additiveIteration(Collection, BiFunction)}, but the previous results can be mapped.
*
* #param <X>
* #param <Y>
* #param col
* #param loopIteration
* #param mapper
*/
public static <X, Y> void mappedCumulativeIteration(final Collection<X> col, final BiFunction<Map<String, Y>, X, Y> loopIteration, final Function<X, String> mapper) {
final Map<String, Y> previous = new LinkedHashMap<>();
col.forEach(x -> previous.put(mapper.apply(x), loopIteration.apply(previous, x)));
}
additionally as #daniu has pointed out you could achieve this with a collector, if you want to collect the given data.
col.stream().<List<Y>>collect(()->new ArrayList<>(), (pre, current) -> pre.add(loopIteration.apply(pre, current)), List::addAll);
Or as a standalone Collector
/**
* #author levent.dag
* https://stackoverflow.com/users/9648047/levent-dag
*
* naming idea with "akuzminykh"
* https://stackoverflow.com/users/12323248/akuzminykh , 02.06.2020
*
* <pre>
* Cumulative Iteration:
* the process of iterating with the results of the previous iterations
*
* definition:
* D domain (collection of X)
* X ∈ of domain, Data/Object/Value
* R results of previous iterations (List<Y>)
*
* f(R, X) iteration cycle/Function for current X element with the knowledge of previous iteration results R
*
*
* for X ∈ D {
* R.add(R, X)
* }
*
* ORDER sensible! use ordered Collections such as Lists and so on.
* </pre>
*
* #param <OBJECT>
* #param <RESULT>
*/
public class CumulativeListCollector<OBJECT, RESULT> implements Collector<OBJECT, List<RESULT>, List<RESULT>> {
private final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration;
public CumulativeListCollector(final BiFunction<List<RESULT>, OBJECT, RESULT> loopIteration) {
this.loopIteration = loopIteration;
}
public static <O,R> CumulativeListCollector<O, R> of(final BiFunction<List<R>, O, R> loopIteration) {
return new CumulativeListCollector<>(loopIteration);
}
#Override
public Supplier<List<RESULT>> supplier() {
return ()->new ArrayList<RESULT>();
}
#Override
public BiConsumer<List<RESULT>, OBJECT> accumulator() {
return (pre, current) -> pre.add(this.loopIteration.apply(pre, current));
}
#Override
public Function<List<RESULT>, List<RESULT>> finisher() {
return Function.identity();
}
#Override
public BinaryOperator<List<RESULT>> combiner() {
return (left, right)->{left.addAll(right); return left;};
}
#Override
public Set<Characteristics> characteristics() {
return Set.of();
}
}
Related
Q: Given a log file with API names, start and end timestamps, write a program that prints the average latency for each API call.
It was asked in google interview, my solution got rejected. So, want to know how can this be solved in optimized way.
$ cat log
get_foo start 2222222100
get_foo end 2222222150
get_bar start 2222222200
get_foo start 2222222220
get_bar end 2222222230
get_foo end 2222222250
solution :
$ cat log | myprog
get_foo: average = 40
get_bar: average = 30
I suggest you to breakdown the process to simplify the complexity of your problem.
Here could be a good starting point about how to define the process :
Done in Java, it could lead to this :
public class Program {
// The HashMap which contains api keys and object wrappers associated to it.
private Map<String, ApiCall> hashMap = new HashMap<>();
/**
* getHashMap
* Setter of the hashMap which contains api keys and object wrappers
* associated to it.
* #return
*/
public Map<String, ApiCall> getHashMap() {
return hashMap;
}
/**
* setHashMap
* Getter of the hashMap which contains api keys and object wrappers
* associated to it.
* #param hashMap
*/
public void setHashMap(Map<String, ApiCall> hashMap) {
this.hashMap = hashMap;
}
/**
* getNewApiCall
* #return a new ApiCall wrapper object
*/
public ApiCall getNewApiCall() {
return new ApiCall();
}
/**
* main
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
Program app = new Program();
// Arbitrary path to test with my environment
String path = args.length > 1 ? args[0] : "/home/user/test";
// Read all lines from your log file
List<Object> lines = Arrays.asList(
Files.lines(
Paths.get(new File(path).getPath())
).toArray()
);
for (Object o:lines) {
String s = o.toString().trim();
// If it's not and empty line
if (!s.isEmpty()) {
/*
* Split the lines into array with
* [0] = api_name, [1] start or end, [2] timestamp
*/
String[] values = s.split(" ");
// Add the API call to a hashmap without any value
app.getHashMap().put(values[0], null);
// Here you have all name of calls of your API
/*
* Now for each api call, wrap it into an object that will
* handle the average computation, the array of start
* timestamps and the array of end timestamps
*/
ApiCall apiCall = app.getHashMap().get(values[0]);
// Create and object for wrapping starting and ending timestamps
if (apiCall == null) {
apiCall = app.getNewApiCall();
}
/*
* If the line is a start then parse the last value to a long
* and add it to the object wrapper to further compute for the
* average
*/
if (values[1].equals("start")) {
apiCall.addStart(Long.parseLong(values[2]));
}
/*
* Else it is a end timestamp then parse the last value of the
* line to a long and add it to the object wrapper to further
* compute for the average
*/
else {
apiCall.addEnd(Long.parseLong(values[2]));
}
// Add the new incremented object wrapper to the API key
app.getHashMap().put(values[0], apiCall);
}
}
/*
* Stream hashmap entries (API keys) and print the key and the average
* value for each
*/
app.getHashMap().entrySet().forEach(
ks -> System.out.println(
ks.getKey()+" average="+ks.getValue().getAverage()
)
);
}
}
The class leading to object to wrap starting and ending timestamps for a specific API call for further computation.
/**
* ApiCall
* Class allowing to collect starting timestamps and ending timestamp for
* an API call. Compute the average on each addition.
* #author user
* #since 12 sept. 2019
*/
public class ApiCall {
private List<Long> start;
private List<Long> end;
private double average;
public ApiCall() {
start = new ArrayList<>();
end = new ArrayList<>();
}
public void addStart(Long l) {
start.add(l);
setAverage(computeAverage());
}
public void addEnd(Long l) {
end.add(l);
setAverage(computeAverage());
}
public double getAverage() {
return this.average;
}
private void setAverage(Double average) {
this.average = average;
}
private double computeAverage() {
return
(
end.stream().mapToLong(Long::longValue).average().orElse(0.0)
- start.stream().mapToLong(Long::longValue).average().orElse(0.0)
);
}
}
I just did this to give you a starting point about how to do. Don't copy/paste because the code is badly written and there is surely errors about the average computation as you can see in the output :
get_bar average=2.22222223E9
get_foo average=2.22222225E9
Hope it helps.
The following is a part source code of org.apache.commons.lang3.builder.EqualsBuilder. What is the difference between pair and swappedPair ? why not swappedPair = Pair.of(pair.getRight(), pair.getLeft());
static Pair<IDKey, IDKey> getRegisterPair(final Object lhs, final Object rhs) {
final IDKey left = new IDKey(lhs);
final IDKey right = new IDKey(rhs);
return Pair.of(left, right);
}
/**
* <p>
* Returns <code>true</code> if the registry contains the given object pair.
* Used by the reflection methods to avoid infinite loops.
* Objects might be swapped therefore a check is needed if the object pair
* is registered in given or swapped order.
* </p>
*
* #param lhs <code>this</code> object to lookup in registry
* #param rhs the other object to lookup on registry
* #return boolean <code>true</code> if the registry contains the given object.
* #since 3.0
*/
static boolean isRegistered(final Object lhs, final Object rhs) {
final Set<Pair<IDKey, IDKey>> registry = getRegistry();
final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs);
final Pair<IDKey, IDKey> swappedPair = Pair.of(pair.getLeft(), pair.getRight());
return registry != null
&& (registry.contains(pair) || registry.contains(swappedPair));
}
When I try to compile I get an error message for my makeUnion method and I'm guessing I will get one for makeIntersection too. I'm not sure why this is, or how to implement makeUnion if I want to add a set interface to the new set. Can someone explain to me what I am doing wrong?
public class Set<T> implements SetInterface<T>
{
private HashSet<T> set;
/**
* Constructs a new empty set.
*/
public Set () {
set = new HashSet <>();
}
/**
* Constructs a new set containing the elements in the specified collection.
* Default load factor of 0.75 and initial capacity of 50.
*
* #param c- the collection whose elements are to be place into this set
*/
public Set(Collection <? extends T> c) {
set = new HashSet<>(Math.max((int) (c.size()/.75f) + 1, 50));
set.addAll(c);
}
/**
* Constructs a new empty set. Default load factor of 0.75.
*
* #param initialCapacity- the initial capacity of the hash table
*/
public Set(int initialCapacity) {
set = new HashSet <>(initialCapacity);
}
/**
* Constructs a new empty set.
* Hashmap has specified initial capacity and specified load factor.
*
* #param initialCapacity- the initial capacity of the hash table
* loadFactor- the load factor of the hash map
*/
public Set(int initialCapacity, float loadFactor) {
set = new HashSet <>(initialCapacity, loadFactor);
}
/**
* Add an item of type T to the interface Duplicate items will not be
* added to the set.
*
* #param itemToAdd - what to add.
*/
public void add(T itemToAdd) {
set.add(itemToAdd);
}
/**
* Removes an item from the set ( if the item is in the set) If the item is not
* in the set this operation does nothing
*
* #param item to remove.
*/
public void remove( T itemToDelete) {
set.remove(itemToDelete);
}
/**
* Return if the SetInterface contains an item
*
* #param itemToCheck. The item you are looking for
* #return true if found. False if not found.
*/
public boolean contains( T itemToCheck) {
return set.contains(itemToCheck);
}
/**
* Make a union of two sets. We add all items in either set to a new set and
* return the new set.
*
* #param the 'other' set to add to our set.
* #return A new set which is the union of the two sets.
*/
public Set<T> makeUnion( SetInterface<T> otherSet) {
return set.addAll(otherSet);
}
/**
* Make an intersection of two sets. We add create a new set which only has
* items in it that are contained in both sets.
*
* #param the 'other' set to intersect with
* #return A new set which is the intersection of the two sets.
*/
public Set<T> makeIntersection( SetInterface<T> otherSet) {
return set.retainAll(otherSet);
}
/**
* Return an iterator for the set. This is used to walk thought all elements
* in the set
*
* #return The iterator
*/
public Iterator<T> getIterator() {
return set.iterator();
}
/**
* Tell the caller how many elements are in the set
*
* #return int with the number of elements
*/
public int size() {
return set.size();
}
}
interface SetInterface<T> {
void add(T itemToAdd);
public void remove( T itemToDelete);
public boolean contains( T itemToCheck);
public Set<T> makeUnion( SetInterface<T> otherSet);
public Iterator<T> getIterator();
public int size();
HashSet<T> getSet();
}
public class Set<T> implements SetInterface<T>
{
private HashSet<T> set;
public HashSet<T> getSet() {
return set;
}
/**
* Constructs a new empty set.
*/
public Set () {
set = new HashSet <>();
}
/**
* Constructs a new set containing the elements in the specified collection.
* Default load factor of 0.75 and initial capacity of 50.
*
* #param c- the collection whose elements are to be place into this set
*/
public Set(Collection <? extends T> c) {
set = new HashSet<>(Math.max((int) (c.size()/.75f) + 1, 50));
set.addAll(c);
}
/**
* Constructs a new empty set. Default load factor of 0.75.
*
* #param initialCapacity- the initial capacity of the hash table
*/
public Set(int initialCapacity) {
set = new HashSet <>(initialCapacity);
}
/**
* Constructs a new empty set.
* Hashmap has specified initial capacity and specified load factor.
*
* #param initialCapacity- the initial capacity of the hash table
* loadFactor- the load factor of the hash map
*/
public Set(int initialCapacity, float loadFactor) {
set = new HashSet <>(initialCapacity, loadFactor);
}
/**
* Add an item of type T to the interface Duplicate items will not be
* added to the set.
*
* #param itemToAdd - what to add.
*/
public void add(T itemToAdd) {
set.add(itemToAdd);
}
/**
* Removes an item from the set ( if the item is in the set) If the item is not
* in the set this operation does nothing
*
* #param item to remove.
*/
public void remove( T itemToDelete) {
set.remove(itemToDelete);
}
/**
* Return if the SetInterface contains an item
*
* #param itemToCheck. The item you are looking for
* #return true if found. False if not found.
*/
public boolean contains( T itemToCheck) {
return set.contains(itemToCheck);
}
/**
* Make a union of two sets. We add all items in either set to a new set and
* return the new set.
*
* #param the 'other' set to add to our set.
* #return A new set which is the union of the two sets.
*/
public Set<T> makeUnion( SetInterface<T> otherSet) {
set.addAll(new java.util.ArrayList<T>(otherSet.getSet()));
return this;
}
/**
* Return an iterator for the set. This is used to walk thought all elements
* in the set
*
* #return The iterator
*/
public Iterator<T> getIterator() {
return set.iterator();
}
/**
* Tell the caller how many elements are in the set
*
* #return int with the number of elements
*/
public int size() {
return set.size();
}
}
Scenario:
I've two reports: Main Report (let's call it, A) and sub-report (let's call it, B).
Report A contains sub-report B at the detail band, so sub-report B is displayed for each element at the Report A datasource. Sub-report B also returns a variable to the Main report A.
What I want is to sum those return values from sub-report B and totalize them at the Main report summary.
To do that, I have tried to create a new report variable that sum those returns values... Something like this:
However, I've found that such variables expression are always evaluated before the band detail is rendered, so I always miss the first sub-report return value...
Sadly, the evaluation time (as this link says) cannot be changed on those kind of variables, so I'm stuck...
After been struggling with this for some hours... and searching the internet for a solution... I came with a Workaround (the enlightening forums were these ones: one and two).
First, you need to define a java Class Helper that allows you calculate some arithmetic operation, in my case a Sum operation. I defined these classes:
package reports.utils;
import java.util.Map;
/**
* Utility that allows you to sum Integer values.
*/
public class SumCalculator {
/**
* Stores a map of {#code SumCalculator} instances (A Map instance per thread).
*/
private static final ThreadLocalMap<String, SumCalculator> calculatorsIndex = new ThreadLocalMap<>();
/**
* The sum total.
*/
private int total = 0;
/**
* No arguments class constructor.
*/
private SumCalculator() {
super();
}
/**
* Instance a new {#code SumCalculator} with the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return the new {#code SumCalculator} instance
*/
public static SumCalculator get(String id) {
Map<String, SumCalculator> map = calculatorsIndex.get();
SumCalculator calculator = map.get(id);
if (calculator == null) {
calculator = new SumCalculator();
map.put(id, calculator);
}
return calculator;
}
/**
* Destroy the {#code SumCalculator} associated to the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return {#code null}
*/
public static String destroy(String id) {
Map<String, SumCalculator> map;
map = calculatorsIndex.get();
map.remove(id);
if (map.isEmpty()) {
calculatorsIndex.remove();
}
return null;
}
/**
* Resets the {#code SumCalculator} total.
*
* #return {#code null}
*/
public String reset() {
total = 0;
return null;
}
/**
* Adds the given integer value to the accumulated total.
*
* #param i an integer value (can be null)
* #return {#code null}
*/
public String add(Integer i) {
this.total += (i != null) ? i.intValue() : 0;
return null;
}
/**
* Return the accumulated total.
*
* #return an Integer value (won't be null, never!)
*/
public Integer getTotal() {
return this.total;
}
}
package reports.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Thread Local variable that holds a {#code java.util.Map}.
*/
class ThreadLocalMap<K, V> extends ThreadLocal<Map<K, V>> {
/**
* Class Constructor.
*/
public ThreadLocalMap() {
super();
}
/* (non-Javadoc)
* #see java.lang.ThreadLocal#initialValue()
*/
#Override
protected Map<K, V> initialValue() {
return new HashMap<>();
}
}
Second, at your jasper report, you need to define four text fields:
1) A text field that iniatializes your calculator; it should be (ideally) at the title section of the report and should have an expression like this: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").reset(). This text field should have the evaluation time: NOW.
2) A text field that calls the increment function (i.e. SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").add($V{SUB_REPORT_RETURN_VALUE}). This text field will reside at your detail band, after the subreport element; and it should have the evaluation time: BAND (this is very important!!)
3) A text field that prints the calculator total. This text field will reside at your summary band, it will evaluate to NOW. Its expression will be: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").getTotal()
4) A text field that destroy the calculator. This text field will also reside at your summary band and must appear after the text field 3. The text field should have an expression like: SumCalculator.destroy("$V{SUB_REPORT_RETURN_VALUE}"). This text field should have the evaluation time: NOW.
Also, the text fields: 1, 2, and 4, should have the attribute "Blank when Null", so they will never be printed (that's why those java operations always return null).
And That's it. Then, your report can look something like this:
if i understand the problem, you can not summarize the amount returned by the sub report in the main report, i had the same problem and i solved in this way.
1.- Create a class which extends from net.sf.jasperreports.engine.JRDefaultScriptlet. and override the method beforeReportInit()
this is the code from this class.
package com.mem.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
public class SumarizacionSubtotales extends JRDefaultScriptlet {
private final Log log = LogFactory.getLog(getClass());
private Double total;
public Double getTotal() {
return total;
}
public Double add(Double cantidad) {
if(log.isDebugEnabled())log.debug("AGREGANDO LA CANTIDAD : " + cantidad);
this.total += cantidad;
return cantidad;
}
#Override
public void beforeReportInit() throws JRScriptletException {
if(log.isDebugEnabled())log.debug("beforeReportInit");
total = 0.0D;
}
}
2.- add your project's jar in your ireport's classpath.
3.- Replace the class of the REPORT scriptlet.
in the properties with your class.
3.- add in the group footer where you want to print the value returned by the sub-report a textfield with the following expression.
$P{REPORT_SCRIPTLET}.add( $V{sum_detalles} )
In this case $V{sum_detalles} is a variable in the main report which contains the value returned by the sub-report.
4.- Add in the Last page footer another textfield with the following expression.
$P{REPORT_SCRIPTLET}.getTotal()
Merged with Genetic Programming help.
I need some guidance on a java project. I'm to develop a human genetic(family) tree.
This is the subject:
Each human cell contains 23 pairs of chromosomes numbered from 1 to 22,and a pair of sex chromosomes: XX in females and XY in man. During fertilization, the 22 chromosomes + (X or Y) of the man merges with the 22 + X chromosome of the woman. This results in 22 pairs of chromosomes + (X or Y) in the cell that will form the future baby. The 23rd chromosome transmitted by the father (an X or Y) will determine the sex of the child (XX for a girl, XY for a boy).
Each chromosome carries many genes (encoding almost everything, a characteristic morphological, physiological, behavioral). Due to pairs of chromosomes, the genetic information is duplicated (except for parts of the sex chromosomes). Each copy of a gene is called an allele. So that means for example, if the a gene is responsible for the color of an eye, then the allele is blue.
The genetic information expressed as a consequence of the combined expression of alleles being present. A dominant allele is always expressed in the genome of its bearer. However, if information from one allele is not expressed when a dominant allele of the same gene is present, it is a recessive allele. The peculiarity of the recessive allele of a gene is that it can be present in the genome and transmitted over several generations without it is expressed in the phenotype its bearers. If there is no dominant allele, two copies of the gene have the same recessive allele (homozygous recessive) then the recessive character is expressed. Through the use of family tree, it is possible to determine the expression of a gene within a family.
The program should be able to do the following:
generate a simplified version relied on 23 chromosomes and allow the user to place genes on chromosomes then simulate replication, mitosis, meiosis and fusion of the chromosomes and display the locations of genes on the resulting cells.
allow to draw genealogical trees and deduced probabilities (or certainty) on the expression of genes on a person's family tree.
So far so good i've created a class Gene and a class Chromosome. Next, i thought about creating a class "Parent" for example and creating 23 chromosomes in it. But before doing that i want to make the 23rd chromosome different for a man/woman. Then simulates replication, crossovers, mitosis etc.. I don't know if i'm on the right track. I also don't know how to specify that a particular allele/gene is recessive or dominant. For the moment my classes only act in a random manner.
Gene.java
import java.util.Random;
/**
* #author mkab
*
*/
public class Gene implements Cloneable {
private Object allele;
public Gene(){
super();
}
public Gene(Object allele){
super();
this.allele = allele;
}
/**
* Randomly selects a trait from trait1 or trait2 and returns a new Gene with that trait
* #param trait1
* #param trait2
*
* #return a new Gene
*/
public Gene randomAllele(Object trait1, Object trait2){
Object allele = null;
Random rand = new Random();
int i = rand.nextInt(2);// generate between 0 and 2: only 2 possibilities: 0 or 1
switch(i){
case 0:
allele = trait1;
break;
case 1:
allele = trait2;
break;
}
return new Gene(allele);
}
public Gene clone() throws CloneNotSupportedException{
Gene g;
g = (Gene) super.clone();
return g;
}
/**
* #param allele the allele to set
*/
public void setAllele(Object allele) {
this.allele = allele;
}
/**
* #return the allele
*/
public Object getAllele() {
return allele;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "Gene [allele=" + allele +"]";
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.Iterator;
/**
* Class that creates a pair of chromosome by adding random genes
* #author mkab
*
*/
public class Chromosome implements Cloneable {
/**
* the user can put as many genes as possible on the chromosome
*/
private ArrayList<Gene> genes = new ArrayList<Gene>();
public Chromosome(){
super();
}
public Chromosome(ArrayList<Gene> genes){
this.genes = genes;
}
/**
* Add a gene object to this chromosomes list.
*/
public void addGene(Gene gene) {
genes.add(gene);
}
/**
*creates a copy of a chromosome
*/
#SuppressWarnings("unchecked")
#Override
public Chromosome clone()throws CloneNotSupportedException{
Chromosome c;
c = (Chromosome) super.clone();
c.genes = (ArrayList<Gene>)this.genes.clone();
//Iterator<Gene> it = c.genes.iterator();
/*Gene tmp;
while(it.hasNext()){
}*/
return c;
}
/**
* #return the genes
*/
public ArrayList<Gene> getGenes() {
return genes;
}
/**
* #param genes the genes to set
*/
public void setGenes(ArrayList<Gene> genes) {
this.genes = genes;
}
/**
*
* #return
*/
public int getSize(){
return genes.size();
}
/**
* #return a gene at an index i of the ArrayList
* #param index - the index at which to return a gene
*/
public Gene getGenes(int index) {
return genes.get(index);
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "Chromosome [genes=" + genes + "]";
}
}
Thanks