I have started experimenting with the Jenetics library, however I am having some issues with trying to make a very easy "custom" set of gene/chromosomes.
What I tried to do was to create a custom chromosome with a different (random) number of custom genes inside. The genes simply contain an integer value, just for the sake of simplicity. For the same simplicity, the contents of a gene can only be numbers ranging from 0 to 9 and a Gene is considered valid only if it does NOT contain the number 9 (again, retardedly simple, but I just wanted to make them custom)
Here is my code:
CustomGene:
public class CustomGene implements Gene<Integer, CustomGene> {
private Integer value;
private CustomGene(Integer value) {
this.value = value;
}
public static CustomGene of(Integer value) {
return new CustomGene(value);
}
public static ISeq<CustomGene> seq(Integer min, Integer max, int length) {
Random r = RandomRegistry.getRandom();
return MSeq.<CustomGene>ofLength(length).fill(() ->
new CustomGene(random.nextInt(r, min, max))
).toISeq();
}
#Override
public Integer getAllele() {
return value;
}
#Override
public CustomGene newInstance() {
final Random random = RandomRegistry.getRandom();
return new CustomGene(Math.abs(random.nextInt(9)));
}
#Override
public CustomGene newInstance(Integer integer) {
return new CustomGene(integer);
}
#Override
public boolean isValid() {
return value != 9;
}
}
CustomChromosome:
import org.jenetics.Chromosome;
import org.jenetics.util.ISeq;
import org.jenetics.util.RandomRegistry;
import java.util.Iterator;
import java.util.Random;
public class CustomChromosome implements Chromosome<CustomGene> {
private ISeq<CustomGene> iSeq;
private final int length;
public CustomChromosome(ISeq<CustomGene> genes) {
this.iSeq = genes;
this.length = iSeq.length();
}
public static CustomChromosome of(ISeq<CustomGene> genes) {
return new CustomChromosome(genes);
}
#Override
public Chromosome<CustomGene> newInstance(ISeq<CustomGene> iSeq) {
this.iSeq = iSeq;
return this;
}
#Override
public CustomGene getGene(int i) {
return iSeq.get(i);
}
#Override
public int length() {
return iSeq.length();
}
#Override
public ISeq<CustomGene> toSeq() {
return iSeq;
}
#Override
public Chromosome<CustomGene> newInstance() {
final Random random = RandomRegistry.getRandom();
ISeq<CustomGene> genes = ISeq.empty();
for (int i = 0; i < length; i++) {
genes = genes.append(CustomGene.of(Math.abs(random.nextInt(9))));
}
return new CustomChromosome(genes);
}
#Override
public Iterator<CustomGene> iterator() {
return iSeq.iterator();
}
#Override
public boolean isValid() {
return iSeq.stream().allMatch(CustomGene::isValid);
}
}
Main:
import org.jenetics.Genotype;
import org.jenetics.Optimize;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.util.Factory;
import org.jenetics.util.RandomRegistry;
import java.util.Random;
public class Main {
private static int maxSum = - 100;
private static Integer eval(Genotype<CustomGene> gt) {
final int sum = gt.getChromosome().stream().mapToInt(CustomGene::getAllele).sum();
if(sum > maxSum)
maxSum = sum;
return sum;
}
public static void main(String[] args) {
final Random random = RandomRegistry.getRandom();
Factory<Genotype<CustomGene>> g =
Genotype.of(CustomChromosome.of(CustomGene.seq(0, 9, Math.abs(random.nextInt(9)) + 1)));
Engine<CustomGene, Integer> engine = Engine
.builder(Main::eval, g)
.optimize(Optimize.MAXIMUM)
.populationSize(100)
.build();
Genotype<CustomGene> result = engine.stream().limit(10000)
.collect(EvolutionResult.toBestGenotype());
System.out.println(eval(result));
result.getChromosome().stream().forEach(i -> {
System.out.print(i.getAllele() + " ");
});
System.out.println();
System.out.println(maxSum);
}
}
I do not understand why I get this output:
13 (evaluated result)
1 8 0 4 (all the alleles form the genes of the chosen chromosome)
32 (the actual maximum fitness found)
We can clearly see a difference between the genotype which had the biggest fitness function and the chosen genotype. Why?
I know I'm doing something wrong and it's probably a silly mistake, but I really can't seem to understand what I am doing wrong. Could you please help me out?
Lots of thanks!
As posted by the creator of the library here, the answer was:
you violated the contract of the Chromosome.newInstance(ISeq) method. This method must return a new chromosome instance. After fixing this
#Override
public Chromosome<CustomGene> newInstance(ISeq<CustomGene> iSeq) {
return new CustomChromosome(iSeq);
}
Related
I am trying to make a class (and a few subclasses and interfaces) to represent a Polynomial. First I have a monomial class which has fields for a coefficient and degree of a Monomial.
public class Monomial {
int coef;
int degree;
public Monomial(int coef) throws IllegalArgumentException {
super();
this.degree = 1;
this.coef = coef;
}
public Monomial(int degree, int coef) throws IllegalArgumentException {
if (this.degree < 0) {
throw new IllegalArgumentException("non positive degree");
}
this.coef = coef;
this.degree = degree;
}
public int getDegree() {
return this.degree;
}
public int getCoef() {
return this.coef;
}
public boolean sameMonomial(Monomial that) {
return this.coef == that.getCoef()
&& this.degree == that.getDegree();
}
}
Next, I have two classes, which implement an interface called ILoMonomial. The ILo stands for (Interface List-of) and it used to represent a list of Monomials.
Therefore, the class MtLoMonomial is an empty list and the base case of the list, having no fields. The ConsLoMonomial class has two fields, a Monomial as the (first) item in the list, and An ILoMonomial as the (rest of the list).
public interface ILoMonomial {
boolean findAnyDupes();
boolean findAnyDupesHelper(int degree);
boolean findSameHelper(Monomial that);
boolean findSame(ILoMonomial that);
}
public class MtLoMonomial implements ILoMonomial {
MtLoMonomial(){}
#Override
public boolean findAnyDupes() {
return true;
}
#Override
public boolean findAnyDupesHelper(int degree) {
return true;
}
#Override
public boolean findSameHelper(Monomial that) {
return false;
}
#Override
public boolean findSame(ILoMonomial that) {
return false;
}
}
public class ConsLoMonomial implements ILoMonomial {
Monomial first;
ILoMonomial rest;
ConsLoMonomial(Monomial first, ILoMonomial rest) {
this.first = first;
this.rest = rest;
}
#Override
public boolean findAnyDupes() {
return this.rest.findAnyDupesHelper(this.first.getDegree()) &&
this.rest.findAnyDupes();
}
#Override
public boolean findAnyDupesHelper(int degree) {
return degree == this.first.degree;
}
public boolean findSameHelper(Monomial that) {
return that.sameMonomial(this.first);
}
#Override
public boolean findSame(ILoMonomial that) {
if (that.findSameHelper(this.first)) {
return true;
} else {
return that.findSame(this.rest);
}
}
}
Finally, I have my Polynomial class, which is where I am running into trouble on how to go about implementing the samePolynomial class. In this class, the only field I have is the ILoMonomial.
I have no idea how to go about this. I have a few helper methods in the classes which implement ILoMonomial (findSame, and findSameHelper)
(but as of now only findSameHelper works and possibly only for the first item in the list).
Here is some example code
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class ExamplesPolynomial {
Monomial oneRaisedToFourth = new Monomial(1, 4);
Monomial twoRaisedToOne = new Monomial(2, 1);
Monomial twoSquared = new Monomial(2 , 2);
Monomial threeXSquared = new Monomial(3, 2);
Monomial five = new Monomial(5, 1);
Monomial coefOf2 = new Monomial(2);
ILoMonomial threeXSquaredPlusFive = new ConsLoMonomial(
threeXSquared, new ConsLoMonomial(
five, new MtLoMonomial()));
ILoMonomial ListOfMonomial1 = new ConsLoMonomial(oneRaisedToFourth,
new MtLoMonomial());
ILoMonomial duplicateDegree = new ConsLoMonomial(twoRaisedToOne,
new ConsLoMonomial(coefOf2, new MtLoMonomial()));
ILoMonomial threeXSquaredPlusFive_Reversed = new ConsLoMonomial(five,
new ConsLoMonomial(threeXSquared, new MtLoMonomial()));
Polynomial error = new Polynomial(duplicateDegree);
Polynomial fine = new Polynomial(threeXSquaredPlusFive);
// passes
#Test(expected = IllegalArgumentException.class)
public void testPolynomial(){
Polynomial error = new Polynomial(duplicateDegree);
}
// passes
#Test
public void testPolynomialTrue() {
Polynomial noError = new Polynomial(new ConsLoMonomial(threeXSquared,
new ConsLoMonomial(twoRaisedToOne, new MtLoMonomial())));
}
// passes
#Test
public void testSameMonomial() {
assertTrue(coefOf2.sameMonomial(coefOf2));
assertFalse(coefOf2.sameMonomial(threeXSquared));
}
// passes
#Test
public void testFindSameHelper() {
assertTrue(ListOfMonomial1.findSameHelper(oneRaisedToFourth));
assertFalse(ListOfMonomial1.findSameHelper(threeXSquared));
}
// fails : assertion error
#Test
public void testFindSame() {
assertTrue(threeXSquaredPlusFive.findSameHelper(five));
}
// fails : assertion error
#Test
public void testSamePolynomial() {
Polynomial reverse = new Polynomial(threeXSquaredPlusFive_Reversed);
Polynomial normal = new Polynomial(threeXSquaredPlusFive);
assertTrue(reverse.samePolynomial(normal));
}
}
I'm doing an assignment in which I have created an Appliance class that has a timePasses()method within it. This method re-directs some values that need to be stored within another method that is inside of another class. Here is where I am up to on this:
Appliance
public class ElectricCooker extends Cooker {
public int isOn = -1;
public int isOff = 0;
public int incrementTime;
public int varPass = -1;
#Override
public int currentState() {
if (varPass == 0) {
return isOff;
} else {
return isOn;
}
}
#Override
public void useTime(int defaultTime) {
defaultTime = 15;
incrementTime = 4;
}
#Override
public void timePasses() {
if (varPass == isOff) {
varPass = 0;
} else {
ElectricMeter.getInstance().incrementConsumed(electricityUse);
GasMeter.getInstance().incrementConsumed(gasUse);
WaterMeter.getInstance().incrementConsumed(waterUse);
}
}
ElectricCooker(int electricityUse, int gasUse, int waterUse, int timeOn) {
super(electricityUse, gasUse, waterUse, timeOn);
this.electricityUse = 5 * incrementTime;
this.gasUse = 0 * incrementTime;
this.waterUse = 0 * incrementTime;
this.timeOn = 15 * incrementTime;
}
}
Meter
public class ElectricMeter {
ElectricMeter() {
}
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() {
return instance;
}
public void incrementConsumed(int value) {
System.out.println(value);
}
public int incrementGenerated() {
}
public boolean canGenerate() {
}
public String getConsumed() {
}
public String getGenerated() {
}
}
Main method
public class MainCoursework {
public static void main(String[] args) {
ElectricMeter a = new ElectricMeter();
a.incrementConsumed(//what goes here?);
}
}
So the value from timePasses()has been redirected into an ElectricMeter instance but now I need to return that value to the increentConsumed() method in the meter class and I'm stuck on how to do this. Since the value of electricityConsumed is 20, the output should be 20. But instead I have to pass a parameter into a.incrementConsumed(//pass parameter here) and what ever is passed gets printed out onto the screen instead of the 20 from electrictyUse. Any help on how to do this is appreciated, thanks.
Actually, the incrementConsumed method is indeed implemented as you described:
public void incrementConsumed(int value)
{
System.out.println(value);
}
A method called incrementXXX shouldn't really output anything, should it? It should increment a variable/field:
private int electricityUsed = 0;
public void incrementConsumed(int value)
{
electricityUsed += value;
}
You should declare another method that returns electricityUsed:
public int getElectricityUsed() {
return electricityUsed;
}
Now let's fix your main method.
In your main method, you didn't even create anything that consumes electricity! How can the electric meter incrementConsumed? So remove everything from the main method and create a cooker:
// your constructor looks weird. So I passed in some random arguments..
ElectricCooker cooker = new ElectricCooker(20, 0, 0, 60);
Now call timePasses to simulate that some time passed:
cooker.timePasses();
And print the electricity used:
System.out.println(ElectricMeter.getInstance().getElectricityUsed());
you need to create an instance variable in ElectricMeter and update that value on say incrementConsumed. When you want to print that use accessor of this variable.
public class Electric {
public static void main(String[] args) {
ElectricCooker cooker = new ElectricCooker(1,2,3,4);
//opertion on cooker
//ignoring best way for singleton creation
int electricityUse = ElectricMeter.getInstance().getElectricityUse();
System.out.println(electricityUse);
}
}
class ElectricCooker // extends Cooker
{
public int isOn = -1;
public int isOff = 0;
public int incrementTime;
public int varPass = -1;
public int electricityUse = -1;
public int currentState() {
if (varPass == 0)
return isOff;
else {
return isOn;
}
}
public void useTime(int defaultTime) {
defaultTime = 15;
incrementTime = 4;
}
public void timePasses() {
if (varPass == isOff)
varPass = 0;
else {
ElectricMeter.getInstance().incrementConsumed(electricityUse);
}
}
ElectricCooker(int electricityUse, int gasUse, int waterUse, int timeOn) {
this.electricityUse = 5 * incrementTime;
}
}
class ElectricMeter {
public int electricityUse = -1;
private static ElectricMeter instance = new ElectricMeter();
public static ElectricMeter getInstance() {
return instance;
}
public void incrementConsumed(int value) {
this.electricityUse = value;
}
public int getElectricityUse() {
return electricityUse;
}
}
In ElectricMeter, some operations don't perform what they should.
ElectricMeter.getInstance().incrementConsumed(electricityUse);
should increment something but it writes only in the output:
public void incrementConsumed(int value){
System.out.println(value);
}
You should write it rather :
public void incrementConsumed(int value){
consumed+=value;
}
and add a private int consumed field in ElectricMeter class to store the actual consumed.
And your getConsumed() which has a empty implementation :
public String getConsumed(){
}
should simply return the consumed field and you should return a int value and not a String.
public int getConsumed() {
return consumed;
}
In this way, you can do :
public static void main(String[] args){
ElectricMeter.getInstance().incrementConsumed(20);
int consumed = ElectricMeter.getInstance().getConsumed();
}
I am new to programming and we just learned ArrayLists in my class today and I have an easy question for you guys, I just can't seem to find it in the notes on what to set the passing value equal to. The point of this practice program is to take in a Number Object (that class has already been created) and those Numbers in the ArrayList are supposed to be counted as odds, evens, and perfect numbers. Here is the first couple of lines of the program which is all you should need.
import java.util.ArrayList;
import static java.lang.System.*;
public class NumberAnalyzer {
private ArrayList<Number> list;
public NumberAnalyzer() {
list = new ArrayList<Number>();
}
public NumberAnalyzer(String numbers) {
}
public void setList(String numbers) {
}
What am I supposed to set (String numbers) to in both NumberAnalyzer() and setList()? Thanks in advance for answering a noob question!
NumberAnalyzer test = new NumberAnalyzer("5 12 9 6 1 4 8 6");
out.println(test);
out.println("odd count = "+test.countOdds());
out.println("even count = "+test.countEvens());
out.println("perfect count = "+test.countPerfects()+"\n\n\n");
This is the Lab16b Class that will run the program. ^^
public class Number
{
private Integer number;
public Number()
{
number = 0;
}
public Number(int num)
{
number = num;
}
public void setNumber(int num)
{
number = num;
}
public int getNumber()
{
return 0;
}
public boolean isOdd()
{
return number % 2 != 0;
}
public boolean isPerfect()
{
int total=0;
for(int i = 1; i < number; i++)
{
if(number % i == 0)
{
total = total + i;
}
}
if(total == number)
{
return true;
}
else
{
return false;
}
}
public String toString( )
{
return "";
}
}
Here is the Number class. ^^
Based on the information you provided, this is what I feel NumberAnalyzer should look like. The setList function is presently being used to take a String and add the numbers in it to a new list.
public class NumberAnalyzer {
private List<Number> list;
public NumberAnalyzer() {
this.list = new ArrayList<Number>();
}
public NumberAnalyzer(String numbers) {
setList(numbers);
}
public void setList(String numbers) {
String[] nums = numbers.split(" ");
this.list = new ArrayList<Number>();
for(String num: nums)
list.add(new Number(Integer.parseInt(num)));
}
}
Analyze to learn something.
public static void main(String[] args) {
String temp = "5 12 9 6 1 4 8 6";
NumberAnalyzer analyzer = new NumberAnalyzer(temp);
//foreach without lambda expressions
System.out.println("without Lambda");
for (NeverNumber i : analyzer.getList()) {
i.print();
}
//with the use of lambda expressions, which was introduced in Java 8
System.out.println("\nwith Lambda");
analyzer.getList().stream().forEach((noNumber) -> noNumber.print());
NeverNumber number = new NeverNumber(31);
number.print();
number.setNumber(1234);
number.print();
}
public class NumberAnalyzer {
private List<NeverNumber> list; //List is interface for ArrayList
public NumberAnalyzer(String numbers) {
String[] numb=numbers.split(" ");
this.list=new ArrayList<>();
for (String i : numb) {
list.add(new NeverNumber(Integer.parseInt(i)));
}
}
public void setList(List<NeverNumber> numbers) {
List<NeverNumber> copy=new ArrayList<>();
numbers.stream().forEach((i) -> {
copy.add(i.copy());
});
this.list=copy;
}
public List<NeverNumber> getList() {
List<NeverNumber> copy=new ArrayList<>();
this.list.stream().forEach((i) -> {
copy.add(i.copy());
});
return copy;
}
public NeverNumber getNumber(int index) {
return list.get(index).copy();
}
}
public class NeverNumber { //We do not use the names used in the standard library.
//In the library there is a class Number.
private int number; // If you can use simple types int instead of Integer.
public NeverNumber() {
number = 0;
}
public NeverNumber(int num) {
number = num;
}
private NeverNumber(NeverNumber nn) {
this.number=nn.number;
}
public void setNumber(int num) {
number = num;
}
public int getNumber() {
return this.number;
}
public boolean isOdd() {
return number % 2 != 0;
}
public boolean isPerfect() {
long end = Math.round(Math.sqrt(number)); //Method Math.sqrt(Number) returns a double, a method Math.round(double) returns long.
for (int i = 2; i < end + 1; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
public NeverNumber copy(){
return new NeverNumber(this);
}
public void print() {
System.out.println("for: " + this.toString() + " isPer: " + this.isPerfect() + " isOdd: " + this.isOdd() + "\n");
}
#Override //Every class in Java inherits from the Object class in which it is toString(),
//so we have to override our implementation.
public String toString() {
return this.number + ""; //The object of any class + "" creates a new object of the String class,
//that is for complex types, calls the toString () method implemented in this class,
//override the toString () from the Object class. If the runs, we miss class toString()
//calls from the Object class.
}
}
I'm using Eclipse and I'm using Java. My objective it's to sort a vector, with the bogoSort method
in one vector( vectorExample ) adapted to my type of vector and use the Java sort on other vector (javaVector) and compare them.
I did the tests but it did't work, so I don't know what is failing.
*Note: there are few words in spanish: ordenado = sorted, Ejemplo = Example, maximo = maximun, contenido = content.
EjemploVector class
package vector;
import java.util.NoSuchElementException;
import java.util.Vector;
import java.util.Iterator;
public class EjemploVector <T> {
protected T[] contenido;
private int numeroElementos;
#SuppressWarnings("unchecked")
public EjemploVector () {
contenido = (T[]) new Object[100];
numeroElementos = 0;
}
#SuppressWarnings("unchecked")
public EjemploVector (int maximo) {
contenido = (T[]) new Object[maximo];
numeroElementos = 0;
}
public String toString(){
String toString="[";
for (int k=0; k<numeroElementos;k++){
if (k==numeroElementos-1){
toString = toString + contenido[k].toString();
} else {
toString = toString + contenido[k].toString()+", ";
}
}
toString = toString + "]";
return toString;
}
public boolean equals (Object derecho){
if (!(derecho instanceof Vector<?>)) {
return false;
} else if (numeroElementos != ((Vector<?>)derecho).size()) {
return false;
} else {
Iterator<?> elemento = ((Vector<?>)derecho).iterator();
for (int k=0; k<numeroElementos;k++){
if (!((contenido[k]).equals (elemento.next()))) {
return false;
}
}
return true;
}
}
public void addElement (T elemento){
contenido[numeroElementos++]= elemento;
}
protected T[] getContenido(){
return this.contenido;
}
protected T getContenido (int k){
return this.contenido[k];
}
#SuppressWarnings("unchecked")
protected void setContenido (int k, Object elemento){
this.contenido[k]= (T)elemento;
}
EjemploVectorOrdenadoClass
package vector.ordenado;
import java.util.Arrays;
import java.util.Random;
import vector.EjemploVector;
public class EjemploVectorOrdenado<T extends Comparable<T>> extends EjemploVector<T> {
private boolean organized;
public EjemploVectorOrdenado() {
super();
organized = true;
}
public EjemploVectorOrdenado(int maximo) {
super(maximo);
organized = true; //
}
public boolean getOrdenado() {
return this.organized;
}
// Method bogoSort
public void bogoSort() {
if (!this.organized) {
if (this.size() > 0) {
Random generator;
T tempVariable;
int randomPosition;
do {
generator = new Random();
for (int i = 0; i < this.size(); i++) {
randomPosition = generator.nextInt(this.size());
tempVariable = contenido[i];
contenido[i] = contenido[randomPosition];
contenido[randomPosition] = tempVariable;
}
} while (!organized);
}
}
this.organized = true;
}
public void addElement(T elemento) {
super.addElement(elemento);
if (organized && this.size() > 1) {
T penultimo = this.getContenido(this.size() - 2);
T ultimo = this.getContenido(this.size() - 1);
organized = penultimo.compareTo(ultimo) <= 0;
}
}
}
ElementoTest class
package elementos;
import java.io.Serializable;
public class ElementoTest implements Comparable<ElementoTest>, Serializable {
private static final long serialVersionUID = -7683744298261205956L;
private static int numeroElementosTest = 0;
private int clave;
private int valor;
public ElementoTest(int i){
this.clave = i;
this.valor = numeroElementosTest;
numeroElementosTest++;
}
public String toString(){
return ("(" + this.clave + "," + this.valor + ")");
}
public boolean equals (Object derecho){
if (!(derecho instanceof ElementoTest)) {
return false;
} else {
return clave == ((ElementoTest)derecho).clave;
}
}
public char getClave(){
return this.clave;
}
public int getValor(){
return this.valor;
}
#Override
public int compareTo(ElementoTest elemento) {
if (elemento == null){
return -1;
} else if (this.equals(elemento)){
return 0;
} else if (clave < elemento.clave){
return -1;
} else {
return 1;
}
}
}
TESTS
The first it's a stupid test, because it puts elements in order so... really the methods arenĀ“t doing anything, java just compare and it gives correct
I tried to make an unsorted vector adding elements but there appears the java.lang.ClassCastException: [Ljava.... etc.
package vector.ordenado;
import static org.junit.Assert.*;
import java.util.Collections;
import java.util.Vector;
import org.junit.Before;
import org.junit.Test;
import elementos.ElementoTest;
public class EjemploVectorOrdenadoTest {
private Vector<ElementoTest> vectorJava;
private EjemploVectorOrdenado<ElementoTest> vectorExample;
#Before
public void setUp() throws Exception {
vectorJava = new Vector<ElementoTest>(100);
vectorExample = new EjemploVectorOrdenado<ElementoTest>(100);
}
#Test
public void testSortFailTest() {
for (char c = 'a'; c < 'g'; c++) {
vectorJava.addElement(new ElementoTest(c));
vectorExample.addElement(new ElementoTest(c));
}
Collections.sort(vectorJava);
vectorExample.bogoSort();
assertTrue(vectorExample.equals(vectorJava));
assertTrue(vectorExample.getOrdenado());
}
#Test
public void testSort() {
{
vectorJava.addElement(new ElementoTest(1));
vectorJava.addElement(new ElementoTest(3));
vectorJava.addElement(new ElementoTest(2));
vectorExample.addElement(new ElementoTest(3));
vectorExample.addElement(new ElementoTest(2));
vectorExample.addElement(new ElementoTest(1));
}
Collections.sort(vectorJava);
vectorExample.bogoSort();
assertTrue(vectorExample.equals(vectorJava));
assertTrue(vectorExample.getOrdenado());
}
}
Sorry, for the problems and thanks.
The problem is that your test class ElementoTest should implement the Comparable interface. Or you need to provide a Comparator during your comparison.
Does your class ElementtoTest implement Comparable?
If not, it needs to.
I'm suspecting it doesn't, because that's exactly what would cause this error. you'll need to add implements Comparable and then override the int compareTo(Elementtotest e) method, where you specify what criteria you'd like to order the objects based on.
I have what amounts to an Iterator<Integer>... actually it's a class Thing that accepts a Visitor<SomeObject> and calls visit() for a subset of the SomeObjects it contains, and I have to implement Visitor<SomeObject> so it does something like this:
// somehow get all the Id's from each of the SomeObject that Thing lets me visit
public int[] myIdExtractor(Thing thing)
{
SomeCollection c = new SomeCollection();
thing.visitObjects(new Visitor<SomeObject>()
{
public void visit(SomeObject obj) { c.add(obj.getId()); }
}
);
return convertToPrimitiveArray(c);
}
I need to extract an int[] containing the results, and I'm not sure what to use for SomeCollection and convertToPrimitiveArray. The number of results is unknown ahead of time and will be large (10K-500K). Is there anything that would be a better choice than using ArrayList<Integer> for SomeCollection, and this:
public int[] convertToPrimitiveArray(List<Integer> ints)
{
int N = ints.size();
int[] array = new int[N];
int j = 0;
for (Integer i : ints)
{
array[j++] = i;
}
return array;
}
Efficiency and memory usage are of some concern.
It's not too difficult to come up with a class that collects ints in an array (even if you are not using some library which does it for you).
public class IntBuffer {
private int[] values = new int[10];
private int size = 0;
public void add(int value) {
if (!(size < values.length)) {
values = java.util.Arrays.copyOf(values, values.length*2);
}
values[size++] = value;
}
public int[] toArray() {
return java.util.Arrays.copyOf(values, size);
}
}
(Disclaimer: This is stackoverflow, I have not even attempted to compile this code.)
As an alternative you could use DataOutputStream to store the ints in a ByteArrayOutputStream.
final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final DataOutputStream out = new DataOutputStream(byteOut);
...
out.writeInt(value);
...
out.flush();
final byte[] bytes = byteOut.toByteArray();
final int[] ints = new int[bytes.length/4];
final ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
final DataInputStream in = new DataOutputStream(byteIn);
for (int ct=0; ct<ints.length; ++ct) {
ints[ct] = in.readInt();
}
(Disclaimer: This is stackoverflow, I have not even attempted to compile this code.)
You could look at something like pjc to handle this. That is a collections framework made for primitives.
for benchmarking's sake I put together a test program using an LFSR generator to prevent the compiler from optimizing out test arrays. Couldn't download pjc but I assume timing should be similar to Tom's IntBuffer class, which is by far the winner. The ByteArrayOutputStream approach is about the same speed as my original ArrayList<Integer> approach. I'm running J2SE 6u13 on a 3GHz Pentium 4, and with approx 220 values, after JIT has run its course, the IntBuffer approach takes roughly 40msec (only 40nsec per item!) above and beyond a reference implementation using a "forgetful" collection that just stores the last argument to visit() (so the compiler doesn't optimize it out). The other two approaches take on the order of 300msec, about 8x as slow.
edit: I suspect the problem with the Stream approach is that there is the potential for exceptions which I had to catch, not sure.
(for arguments run PrimitiveArrayTest 1 2)
package com.example.test.collections;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PrimitiveArrayTest {
interface SomeObject {
public int getX();
}
interface Visitor {
public void visit(SomeObject obj);
}
public static class PlainObject implements SomeObject
{
private int x;
public int getX() { return this.x; }
public void setX(int x) { this.x = x; }
}
public static class Thing
{
/* here's a LFSR
* see http://en.wikipedia.org/wiki/Linear_feedback_shift_register
* and http://www.ece.cmu.edu/~koopman/lfsr/index.html
*/
private int state;
final static private int MASK = 0x80004;
private void _next()
{
this.state = (this.state >>> 1)
^ (-(this.state & 1) & MASK);
}
public Thing(int state) { this.state = state; }
public void setState(int state) { this.state = state; }
public void inviteVisitor(Visitor v, int terminationPoint)
{
PlainObject obj = new PlainObject();
while (this.state != terminationPoint)
{
obj.setX(this.state);
v.visit(obj);
_next();
}
}
}
static public abstract class Collector implements Visitor
{
abstract public void initCollection();
abstract public int[] getCollection();
public int[] extractX(Thing thing, int startState, int endState)
{
initCollection();
thing.setState(startState);
thing.inviteVisitor(this, endState);
return getCollection();
}
public void doit(Thing thing, int startState, int endState)
{
System.out.printf("%s.doit(thing,%d,%d):\n",
getClass().getName(),
startState,
endState);
long l1 = System.nanoTime();
int[] result = extractX(thing,startState,endState);
long l2 = System.nanoTime();
StringBuilder sb = new StringBuilder();
sb.append(String.format("%d values calculated in %.4f msec ",
result.length, (l2-l1)*1e-6));
int N = 3;
if (result.length <= 2*N)
{
sb.append("[");
for (int i = 0; i < result.length; ++i)
{
if (i > 0)
sb.append(", ");
sb.append(result[i]);
}
sb.append("]");
}
else
{
int sz = result.length;
sb.append(String.format("[%d, %d, %d... %d, %d, %d]",
result[0], result[1], result[2],
result[sz-3], result[sz-2], result[sz-1]));
}
System.out.println(sb.toString());
}
}
static public class Collector0 extends Collector
{
int lastint = 0;
#Override public int[] getCollection() { return new int[]{lastint}; }
#Override public void initCollection() {}
#Override public void visit(SomeObject obj) {lastint = obj.getX(); }
}
static public class Collector1 extends Collector
{
final private List<Integer> ints = new ArrayList<Integer>();
#Override public int[] getCollection() {
int N = this.ints.size();
int[] array = new int[N];
int j = 0;
for (Integer i : this.ints)
{
array[j++] = i;
}
return array;
}
#Override public void initCollection() { }
#Override public void visit(SomeObject obj) { ints.add(obj.getX()); }
}
static public class Collector2 extends Collector
{
/*
* adapted from http://stackoverflow.com/questions/1167060
* by Tom Hawtin
*/
private int[] values;
private int size = 0;
#Override public void visit(SomeObject obj) { add(obj.getX()); }
#Override public void initCollection() { values = new int[32]; }
private void add(int value) {
if (!(this.size < this.values.length)) {
this.values = java.util.Arrays.copyOf(
this.values, this.values.length*2);
}
this.values[this.size++] = value;
}
#Override public int[] getCollection() {
return java.util.Arrays.copyOf(this.values, this.size);
}
}
static public class Collector3 extends Collector
{
/*
* adapted from http://stackoverflow.com/questions/1167060
* by Tom Hawtin
*/
final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
final DataOutputStream out = new DataOutputStream(this.byteOut);
int size = 0;
#Override public int[] getCollection() {
try
{
this.out.flush();
final int[] ints = new int[this.size];
final ByteArrayInputStream byteIn
= new ByteArrayInputStream(this.byteOut.toByteArray());
final DataInputStream in = new DataInputStream(byteIn);
for (int ct=0; ct<ints.length; ++ct) {
ints[ct] = in.readInt();
}
return ints;
}
catch (IOException e) { /* gulp */ }
return new int[0]; // failure!?!??!
}
#Override public void initCollection() { }
#Override public void visit(SomeObject obj) {
try {
this.out.writeInt(obj.getX());
++this.size;
}
catch (IOException e) { /* gulp */ }
}
}
public static void main(String args[])
{
int startState = Integer.parseInt(args[0]);
int endState = Integer.parseInt(args[1]);
Thing thing = new Thing(0);
// let JIT do its thing
for (int i = 0; i < 20; ++i)
{
Collector[] collectors = {new Collector0(), new Collector1(), new Collector2(), new Collector3()};
for (Collector c : collectors)
{
c.doit(thing, startState, endState);
}
System.out.println();
}
}
}
Instead of convertToPrimitiveArray, you can use List.toArray(T[] a):
ArrayList<int> al = new ArrayList<int>();
// populate al
int[] values = new int[al.size()];
al.toArray(values);
For your other concerns, LinkedList might be slightly better than ArrayList, given that you don't know the size of your result set in advance.
If performance is really a problem, you may be better off hand-managing an int[] yourself, and using System.arraycopy() each time it grows; the boxing/unboxing from int to Integer that you need for any Collection could hurt.
As with any performance-related question, of course, test and make sure it really matters before spending too much time optimizing.