Java ArrayList对象被覆盖

Java ArrayList对象被覆盖,java,oop,arraylist,Java,Oop,Arraylist,在这里尝试使用遗传算法,我不明白为什么同一个数组在几行之后返回不同的结果 代码如下: Population(int PopulationSize, ArrayList<Vessel> vessels) { this.PopulationSize = PopulationSize; solutions = new ArrayList(PopulationSize); for (int i = 0; i < PopulationSize; i++) {

在这里尝试使用遗传算法,我不明白为什么同一个数组在几行之后返回不同的结果

代码如下:

Population(int PopulationSize, ArrayList<Vessel> vessels) {
    this.PopulationSize = PopulationSize;
    solutions = new ArrayList(PopulationSize);

    for (int i = 0; i < PopulationSize; i++) {
            Solution s = new Solution(vessels);   
            solutions.add(s);
            System.out.println(i+" : "+solutions.get(i).getFitness());              
    }

    for (int i = 0; i < solutions.size(); i++) {
        System.out.println(solutions.get(i).getFitness());

    }
}
更多源代码`

Solution.java

package geneticalgorithm;

import static java.lang.Math.abs;
import java.util.ArrayList;

public class Solution {

    ArrayList<Vessel> vessels;

    public Solution(ArrayList<Vessel> vessels) {
        this.vessels = new ArrayList<>(vessels);
        generateSolution();
    }

    public void generateSolution() {    
        do {
            for (Vessel vessel : vessels) {
                vessel.generateParams();
            }
        } while(!isValid());
    }

    /* Getters */
    public Vessel getIndividual(int index) {
        return vessels.get(index);
    }

    // Save individual
    public void saveIndividual(int index, Vessel v) {
        vessels.set(index, v);
    }

    public float getFitness() {
        float fitness = 0, BPCost = 0, CHDelay=0, CBDelay=0;

        for (Vessel v : vessels) {
            BPCost += v.DistancePenaltyCost*abs(v.X-v.LowestCostBerthing);
            CHDelay +=  v.TimePenaltyCost*(abs(2*(v.Y + v.HandlingTime - v.SailingTime))/2);
            CBDelay += v.BunkeringDelayCost*v.BunkeringNeeded*(abs(2*(v.BA+v.BunkeringProcessing-v.SailingTime))/2);
        }
        fitness = BPCost + CHDelay + CBDelay;
        return fitness;
    }

    public boolean isValid() {
        boolean XOverlaps, YOverlaps;

        for (Vessel vTemp : vessels) {
            for (Vessel v : vessels) {
                // Initialization 
                    XOverlaps = YOverlaps = false;

                // Checking for X overlaps
                if(v.X > vTemp.X && v.X < (vTemp.X + vTemp.Length))
                    XOverlaps = true;

                // Checking for Y overlaps
                if(v.Y >= vTemp.Y && v.Y <= (vTemp.Y + vTemp.HandlingTime))
                    YOverlaps = true;   

                // Breaking the loop
                if(XOverlaps && YOverlaps)
                    return false;
            }
        }
        return true;
    }


}
Vesser.java

package geneticalgorithm;

import java.util.Random;

public class Vessel {

    Float X,Y,BA;
    Byte Z;

    Float ETA;
    Float Length;
    Float LowestCostBerthing;
    Float HandlingTime;
    Float SailingTime;
    Float DistancePenaltyCost;
    Float TimePenaltyCost;
    Float BunkeringDelayCost;
    Byte BunkeringNeeded;
    Float BunkeringProcessing;  

    void generateParams() {
        Random rand = new Random();
        Float MinBerth = 0.0f, MaxBerth = LowestCostBerthing + Length;

        if(LowestCostBerthing - Length > 0)
            MinBerth = LowestCostBerthing - Length;

        if(MaxBerth > DataLoader.Quay)
            MaxBerth = DataLoader.Quay - Length;

        X = rand.nextFloat() * (MaxBerth - MinBerth) + MinBerth;
        Y = rand.nextFloat() * ((ETA+24) - (ETA+1)) + (ETA+1);

        if(BunkeringNeeded==1)
        {
            Z = (byte) Math.round(Math.random()); // 0 OR 1
            if(Z!=0) {
                BA = Y;
            } else if(Y - ETA < BunkeringProcessing) {
                BA = SailingTime;
            } else if(Y - ETA > BunkeringProcessing) {
                BA = ETA;
            }

        } else {
            Z = 0;
            BA = 0.0f;
        }
    }

}
有什么想法吗?谢谢

在这里尝试使用遗传算法,我不明白为什么同一个数组在几行之后返回不同的结果

每个解决方案都以容器对象列表的形式传递。此列表用于在每个解决方案中创建另一个容器列表,但需要注意的是,新列表仍然包含原始容器对象

还有一些其他字段是计算:

Float X,Y,BA;
Byte Z;
你真的应该考虑将容器的常数与你的解决方案所产生的计算分开。另外,作为旁白,字段应该以小写字母开头,基本体是浮点型,字节而不是最有可能的对象,如果它们是不可变的,则应该是最终的

private final List<VesselCalculation> vesselCalculations = new ArrayList<>();
public Solution(ArrayList<Vessel> vessels) {
    for (Vessel vessel : vessels) {
         vesselCalculations.add(new VesselCalculation(vessel));
    }
    generateSolution();
}
一个想法是拥有一个VesselCalculation对象,该对象将保存计算结果,并具有一个Vessel字段:

因此,解决方案将生成一个要修改的VesselCalculation列表。容器对象将与不同的用户共享 VesselCalculation对象,但将保持不变

private final List<VesselCalculation> vesselCalculations = new ArrayList<>();
public Solution(ArrayList<Vessel> vessels) {
    for (Vessel vessel : vessels) {
         vesselCalculations.add(new VesselCalculation(vessel));
    }
    generateSolution();
}
然后,generateSolution将仅对此特定解决方案局部的VesselCalculation对象进行更改。

getFitness似乎仅使用从血管提取的值

由于每个解决方案都包含相同的血管实例,因此每个解决方案都会在给定血管的特定状态下返回相同的getFitness响应

解决方案的构造函数调用generateSolution,它修改容器的内容。这就是每次创建新解决方案时getFitness结果都会发生变化的原因

我不知道您想要的算法的细节,但似乎每个解决方案都应该有自己的列表副本。它是否应该在其构造函数中创建该副本,或者调用构造函数的任何东西是否负责创建该副本,这取决于您

因为容器对象本身是可变的,并且使用了可变性,所以您还需要复制它们,而不是创建另一个包含对相同对象的引用的列表


在这种情况下,使用不可变集合和不可变对象可以省去很多麻烦。

如果您遇到同样的问题,我可以通过使用解决这个问题。其思想是在数组上循环,并在克隆时逐个复制每个元素。在ArrayList上调用clone函数没有效果,但是在保留相同引用的同时克隆ArrayList


您必须实现可克隆接口,并在手动克隆每个字段时覆盖克隆方法。

您没有发布相关代码。请发布解决方案类。但是从行为上来说,我会说你把适应度存储在某个静态场中。并且请遵守Java命名约定:除非static final,否则字段应始终以小写字母开头。解决方案使用静态字段。让它成为非静态的,每个解决方案都会有自己的价值。这些评论是有见地的猜测,但它们只是猜测。请将其纳入MVCE——到目前为止,我们所拥有的还不完整或无法验证。在将其最小化的过程中,您可能会发现问题所在。如果是这样,请礼貌地在这里提供MVCE和答案。@PhoenixNoor然后显示类定义。每次创建一个新的解决方案,然后调用getFintness更改。尝试使用溶液a=新的溶液容器;System.out.printlna.getFitness;溶液b=新的溶液容器;System.out.printlna.getFitness+,+b.getFitness;所以要么你们有静态场,要么你们保留了一个对血管的引用,并对其进行了修改。你们在修改血管。您的每个解决方案都引用相同的容器。然后对它们进行修改,使每个解决方案都能反映出这些变化。很好的一点是,容器本身也在被修改。我想我已经习惯于不修改这样的东西了,我浏览了一下代码,假设它们不会。是的,可变性在@slim非常重要,当有人有这样的模式时,我们会被绊倒。目的是要有独立的不相关副本,我们如何做到这一点?谢谢你的帮助。请看我的答案@PheonixNoor。更好的解决方案是将常量与计算字段分开。
Float X,Y,BA;
Byte Z;
public class VesselCalculation {
    private final Vessel vessel;
    private float x, y, ba;
    private byte z;
private final List<VesselCalculation> vesselCalculations = new ArrayList<>();
public Solution(ArrayList<Vessel> vessels) {
    for (Vessel vessel : vessels) {
         vesselCalculations.add(new VesselCalculation(vessel));
    }
    generateSolution();
}