1

我有一个关于 Java 中的 HashMap 的问题。为了详细解释这个问题,我将首先发布一些您可以参考的代码。

public void BLASTroute(String args[]) throws IOException, InterruptedException{
            ...
            correctMapping CM = new correctMapping();
            CM.correctMapping(RB.BLASTresults, exists);
            CalculateNewConsensusSequence CNCS = 
                new CalculateNewConsensusSequence();
            char[] consensus = CNCS.calculateNewConsensusSequence(
                CM.newSeq, CM.remindGaps, EMBLreaderReference.sequence, exists);

            HashMap<Integer, ArrayList<String>> gapsFused = 
                new HashMap<Integer, ArrayList<String>>();
            for (Integer i : CM.remindGaps.keySet()) {
                ArrayList<String> newList = CM.remindGaps.get(i);
                gapsFused.put(i, newList);
            }

            GenerateGeneLists GGL = new GenerateGeneLists(
                EMBLreaderReference, CM.newSeq, gapsFused, exists, 
                GQList, allMappedPositions);
            System.out.println(CM.remindGaps.hashCode());
            gapsFused=GGL.generateGeneListSNP(gapsFused);
            System.out.println(CM.remindGaps.hashCode());
            System.out.println(gapsFused.hashCode());
            GGL.generateGeneListFrameShift(gapsFused);

        }

发生以下情况:

在我的课堂上正确映射,我填充了一个名为remindGaps 的全局变量。我稍后在某些功能中使用它,但没有任何反应/一切都按预期工作。

然后,我制作了一个名为 gapsFused 的 HashMap 的副本(我不知道这是否与我的问题有关)。

现在到了有趣的部分:在GenerateGeneLists 类中,我不使用remindGaps HashMap。

但是,函数 generateGeneListSNP 执行后,remindGaps 发生了变化!我也会为您发布代码,以便您可以更好地帮助我:

public GenerateGeneLists(EMBL_reader EMBLreaderReference,
           HashMap<String,ArrayList<String>> newSeq,
           HashMap<Integer,ArrayList<String>> gapsFused, File exists,
           ArrayList<GeneQualifier> GQlist, 
           HashMap<Integer,Integer> allMappedPositions) 
throws InterruptedException{
     this.EMBLreaderReference=EMBLreaderReference;
     this.newSeq=newSeq;
     //this.gapsFused=gapsFused;
     this.exists=exists;
     this.GQlist=GQlist;
     this.allMappedPositions=allMappedPositions;
     for (GeneQualifier GQ : this.GQlist){
        startlist.add(GQ.start);
        stoplist.add(GQ.stop);
        startMap.put(GQ.start,GQ);
    }
}

public HashMap<Integer,ArrayList<String>> generateGeneListSNP(
           HashMap<Integer,ArrayList<String>> gapsFused) 
throws IOException{
    File GQSNP = new File (exists+"/GQsnp.txt");
    BufferedWriter SNP = new BufferedWriter(new FileWriter(GQSNP));
    SNP.write("#Gene_start\tGene_stop\tlocus_tag\tproduct" + 
              "\tputative_SNP_positions(putative_changes)\n");
    HashMap<GeneQualifier,ArrayList<Integer>> GQreminder = 
        new HashMap<GeneQualifier,ArrayList<Integer>>();
    for (String s : newSeq.keySet()){
        ArrayList<String> blub = newSeq.get(s);
        char[] qrySeq = blub.get(0).toCharArray();
        char[] refSeq = blub.get(1).toCharArray();
        int start = Integer.valueOf(blub.get(2));
        int stop = Integer.valueOf(blub.get(3));
        for (int i=0;i<refSeq.length;i++){
            if (qrySeq[i]!=refSeq[i]&&qrySeq[i]!='-'&&qrySeq[i]!='.'){
                if (mismatchList.containsKey(start+i)){
                    ArrayList<Character> blah = mismatchList.get(start+i);
                    blah.add(qrySeq[i]);
                    mismatchList.put(start+i, blah);
                }
                else {
                    ArrayList<Character> blah = new ArrayList<Character>();
                    blah.add(qrySeq[i]);
                    mismatchList.put(start+i,blah);
                }
            }
            else if (qrySeq[i]!=refSeq[i]&&(qrySeq[i]=='-'||qrySeq[i]=='.')){
                if (!gapsFused.containsKey(start+i)){
                    ArrayList<String> qwer = new ArrayList<String>();
                    qwer.add(String.valueOf(qrySeq[i]));
                    gapsFused.put(start+i,qwer);
                }
                else {
                    ArrayList<String> qwer = gapsFused.get(start+i);
                    qwer.add(String.valueOf(qrySeq[i]));
                    gapsFused.put(start+i,qwer);
                }
                if (!deletionPositionsAndCount.containsKey((start+i))){
                    int count = 1;
                    deletionPositionsAndCount.put(start+i, count);
                }
                else {
                    int count = deletionPositionsAndCount.get(start+i);
                    count = count+1;
                    deletionPositionsAndCount.put(start+i, count);
                }
            }
        }
    }
    for (Integer a : mismatchList.keySet()){
        for (int i=0;i<startlist.size();i++){
            int start = startlist.get(i);
            int stop = stoplist.get(i);
            if (a>=start && a<=stop){
                GeneQualifier GQ = startMap.get(start);
                if (!GQreminder.containsKey(GQ)){
                    ArrayList save = new ArrayList<Integer>();
                    save.add(a);
                    GQreminder.put(GQ,save);
                }
                else {
                    ArrayList save = GQreminder.get(GQ);
                    save.add(a);
                    GQreminder.put(GQ,save);
                }
                break;
            }
        }
    }
    for (GeneQualifier GQ : GQreminder.keySet()) {
        ArrayList<Integer> save = GQreminder.get(GQ);
        int start = GQ.start;
        int stop = GQ.stop;
        String locus_tag = 
            GQ.geneFeatures.get("locus_tag").get(0).replace("\n", "");
        String product = 
            GQ.geneFeatures.get("product").get(0).replace("\n", "");
        SNP.write(start + "\t" + stop + "\t" + locus_tag + 
                  "\t" + product + "\t");
        boolean end = false;
        for (int i = 0; i < save.size(); i++) {
            if (i==save.size()-1) end=true;

            int posi = save.get(i);
            SNP.write(posi + "(");
            ArrayList<Character> mismatches = mismatchList.get(posi);
            for (int j = 0; j < mismatches.size(); j++) {
                char snipp = mismatches.get(j);
                if (j == mismatches.size() - 1) {
                    SNP.write(snipp + ")");
                } else {
                    SNP.write(snipp + ",");
                }
            }
            if (end == false){
                SNP.write(",");
            }
        }
        SNP.write("\n");
    }
    SNP.close();
    return gapsFused;
}

如您所见,在这个类中没有使用remindGaps,但它仍然会发生变化。你知道为什么会这样吗?

我测试的是,如果我手动更改 gapsFused (第一个 HashMap 的副本),remindGaps 是否会发生变化。事实并非如此,所以我不认为复制过程出错(例如只指向另一个 HashMap 或引用它)。

为了解决这个问题,我非常感谢您的想法和帮助。

4

4 回答 4

3

您必须记住,在 Java 中,所有对象都作为引用传递。所以,当你这样做时:

ArrayList<String> newList = CM.remindGaps.get(i);

您基本上将 newList 指向与remindGaps 地图中包含的相同列表。现在,即使您使用 gapsFused,对其值的任何更改都会影响内存中相同的底层列表——remindGaps 和 gapsFused 都指向该列表。

将您的复制代码更改为以下内容,看看它是否有所不同:

ArrayList<String> newList = new ArrayList<String>(CM.remindGaps.get(i));

通过这样做,您将创建一个 newList 将指向的新列表,因此将封装更改。

于 2012-06-20T11:16:38.130 回答
0

您的代码非常长且难以阅读(主要是因为它不遵守 Java 命名约定),但我的猜测是您的问题来自于您的地图副本只是将 ArrayList 引用从一个地图复制到另一个地图:

HashMap<Integer, ArrayList<String>> gapsFused = new HashMap<Integer, ArrayList<String>>();
for (Integer i : CM.remindGaps.keySet()) {
    ArrayList<String> newList = CM.remindGaps.get(i);
    gapsFused.put(i, newList);
}

在上面的代码中,您没有创建任何新列表。您只需将相同的列表存储在另一个地图中。如果你需要一个新列表,代码应该是:

Map<Integer, List<String>> gapsFused = new HashMap<Integer, List<String>>();
for (Integer i : CM.remindGaps.keySet()) {
    List<String> newList = new ArrayList<STring>(CM.remindGaps.get(i));
    gapsFused.put(i, newList);
}
于 2012-06-20T11:17:50.477 回答
0

在不分析所有代码的情况下:

HashMap<Integer, ArrayList<String>> gapsFused = new HashMap<Integer, ArrayList<String>>();
for (Integer i : CM.remindGaps.keySet()) {
    ArrayList<String> newList = CM.remindGaps.get(i);
    gapsFused.put(i, newList);
}

在此代码之后 gapFused 将包含作为remindGaps 条目副本的条目,因此这些条目将引用相同的对象(键和值)。因此,如果您在一个 Map 中添加或删除条目,它将对另一个 Map 没有影响,但如果您更改通过一个 Map 访问它的值,您将看到更改也通过另一个 Map 访问它(例如 remingGaps.get(1 ).add("你好"))。

您的代码中使用的名称“newList”令人困惑,因为它不是一个新列表,只是对现有列表的引用......

于 2012-06-20T11:18:21.813 回答
0

由于 the 的值Map是 anArrayList并且您只是在做一个浅拷贝(意味着 newMap具有与第一个相同的引用ListsMap并且对第二个映射中列表的更改将反映在第一个映射中。为避免这种情况,您需要在创建新的Map.

于 2012-06-20T11:18:52.433 回答