shababhsiddique
shababhsiddique

Reputation: 921

Problem with java List<>

I am not familiar much with the java List and arrayList .. i just need something to work smoothly to append and sort.

My algorithm is simple:

set a father string 
add father to speciesList
    mutate father to some new child
    make this new child the future father
    go to step 2

The definitions of ga_ and ga_struct is given here

public class ga_struct {

    public String gene;
    public int fitness;

}


public class ga_{

    public List<ga_struct> vector= new ArrayList<ga_struct>();

        public void sortspecies()
        {
        Collections.sort(vector,new Comparator<ga_struct>() {
        @Override
        public int compare(ga_struct o1, ga_struct o2) {
            int res;
            if(o1.fitness<o2.fitness)
                res=-1;
            else if(o1.fitness>o2.fitness)
                res=1;
            else 
                res=0;
            return res;
                 }
              }
                  );

     }


    public ga_struct mutate(ga_struct parent)
    {
        Random r= new Random();
        ......     do some modification to the parent
        return parent;
    }
}

I have been doing this

        ga_ newSpecies = new ga_();
        Random r= new Random(10);
        ga_struct father= new ga_struct();
        father.gene="123";
        newSpecies.vector.add(father);

        for (int i = 1; i < 10; i++) {
            ga_struct ng = new ga_struct();        
            ng=newSpecies.mutate(father);
            ng.fitness=i;
            newSpecies.vector.add(ng);
            father=ng;          
            System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);

        }

        newSpecies.sortspecies();
        System.out.println("\ncurrent population\n");

        for (int i = 0; i < 10; i++) {
            System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);
        }

The mutator function just alter the String(gene) one character at a time. I just mutated 9 new species from the "father" in the first loop. But.. I dont know why the output of the code is giving me this-

133 with fitness factor 1
433 with fitness factor 2
433 with fitness factor 3
443 with fitness factor 4
453 with fitness factor 5
553 with fitness factor 6
563 with fitness factor 7
563 with fitness factor 8
573 with fitness factor 9

current population

573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9
573 with fitness factor 9

The first loop is proof that mutation is going slowly.. And i also added immediately after a mutation, then why is that later on all of them are just overwritten by the latest edition?

Upvotes: 3

Views: 395

Answers (3)

no.good.at.coding
no.good.at.coding

Reputation: 20371

You're working with a single object everywhere, you never add a new ga_struct instance to the list. Your mutate() method appears to simply modify the parent parameter and returns it - it's still the same object, just modified, which means it's modified everywhere.

public ga_struct mutate(ga_struct parent)
{
    Random r= new Random();
    ......     do some modification to the parent
    return parent;
}

You do create a new instance of ga_struct but you immediately overwrite it by setting the reference to the mutated father (which is still the same instance, just modified):

for (int i = 1; i < 10; i++) {
        ga_struct ng = new ga_struct();        
        ng=newSpecies.mutate(father); //the new ga_struct is overwritten
        ng.fitness=i;
        newSpecies.vector.add(ng);
        father=ng;          
        System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);

    }

Your output in this loop seems to work because you see the modifications to father in the order they happen. However, what you're actually doing is just adding references to the same (modified) object over and over into the List.

Thus, when you finally print them all out, you see 10 duplicate entries in the List.


My suggestion is to change mutate() to return a new instance of ga_struct - you could either create a new object and set it's gene field to be the mutated gene field from parent. Or you could clone parent and then change the clone's gene string. In either case, you will end up returning a new instance of ga_struct which should fix the problem.

public ga_struct mutate(ga_struct parent)
{
    Random r= new Random();
    ga_struct mutant = parent.clone(); 
   //or 
   //ga_struct mutant = new ga_struct();
   //mutant.gene = parent.gene;

    ......     do some modification to the mutant
    return mutant; //now you'll be returning a new object not just a modified one
}

Upvotes: 0

Taylor
Taylor

Reputation: 4086

First off, your object usage is a bit weird.

In mutate, you seem to be changing and returning the father.

This means your list will contain multiple references to the same instance.

to clarify:

public ga_struct mutate(ga_struct parent) //takes in reference to parent
{
    Random r= new Random(); //modifies parent
    ......     do some modification to the parent
    return parent; //return reference to parent
}

And in your main:

    ga_ newSpecies = new ga_();
    Random r= new Random(10);
    ga_struct father= new ga_struct();//instantiate father
    father.gene="123";
    newSpecies.vector.add(father);

    for (int i = 1; i < 10; i++) {
        ga_struct ng = new ga_struct();//create new instance for child
        ng=newSpecies.mutate(father);//set ng as reference to same instance as father, instance instantiated on previous line is discarded
        ng.fitness=i;
        newSpecies.vector.add(ng);
        father=ng;          
        System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);

    }

Try Something more like this:

    public ga_struct mutate(ga_struct parent)
{
    ga_struct ng = new ga_struct();
    ng.gene = father.gene;
    Random r= new Random();
    //do some modification to ng
    return ng;
}

and in your main:

a_ newSpecies = new ga_();
    Random r= new Random(10);
    ga_struct father= new ga_struct();
    father.gene="123";
    newSpecies.vector.add(father);

    for (int i = 1; i < 10; i++) {    
        ga_struct ng=newSpecies.mutate(father);
        ng.fitness=i;
        newSpecies.vector.add(ng);
        father=ng;          
        System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);

    }

    newSpecies.sortspecies();
    System.out.println("\ncurrent population\n");

    for (int i = 0; i < 10; i++) {
        System.out.println(newSpecies.vector.get(i).gene+" with fitness factor "+newSpecies.vector.get(i).fitness);
    }

Upvotes: 3

Dave G
Dave G

Reputation: 9777

You're not creating a new object, you've added the father object 9 times to the vector.

Essentially what you've got is

father -> obj@123

What your List object looks like is [ obj@123, obj@123, obj@123, ... ]

You're going to need to create new instances to record this. I would recommend implementing the "clone()" method to do this.

Upvotes: 1

Related Questions