2012-06-20 3 views
1

자바에서 HashMap과 관련된 문제가 있습니다. 문제를 자세히 설명하기 위해 먼저 참조 할 수있는 코드를 게시 할 것입니다.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); 

     } 

다음이 발생합니다 : 내 클래스 correctMapping에서

, 내가 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을 가리키거나 참조하는 경우).

이 문제를 해결하기 위해 귀하의 아이디어와 도움에 감사드립니다.

+0

필자가 보았 듯이 "예"사용자가 귀하의 예를 지나치게 자세한 것으로 보입니다. 가장 관련성이 높은 코드 섹션을 좁히는 데 시간을 투자해야합니다. 어쨌든, 그것은 자체 포함되어 있지 않습니다 (http://sscce.org/). –

+0

당신이 옳을 수도 있습니다. 문제가있는 곳과 그 특정 지역에서 일어나는 일을 분명하게 지적하고 싶었습니다. 나는 오랫동안 그것에 대해 생각하고 거의 모든 그물을 검색했기 때문에 적어도 한 가지 아이디어에 열망하고 있습니다. 그러나 아무도 약 15 분 안에 글을 쓰지 않으면 코드를 줄입니다. 조언 해 주셔서 감사합니다. – user1365291

답변

3

Java에서 모든 객체가 참조로 전달된다는 것을 기억해야합니다. 당신이 한 때, 다음 remindGaps지도에 포함 된

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

당신은 기본적으로 동일한 목록에 newList을 지적했다. 이제 Fused로 작업하더라도 값에 대한 변경 사항은 메모리에있는 동일한 기본 목록에 영향을줍니다. 즉, Gaps와 GapsFused가 가리키는 위치가 모두 기억됩니다.

는 다음에 복사 코드를 변경하고 차이가 있는지 확인

:

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

당신이 newList가 가리키는되고, 따라서 변경 캡슐화하는 새로운 목록을 작성, 이렇게함으로써를.

+0

대단히 고마워, 나는 그것을 얻지 않기 위해서 눈보라가되어야했다. – user1365291

0

코드가 매우 길고 읽기가 어렵지만 (주로 Java 명명 규칙을 따르지 않기 때문에), 내 생각에 귀하의지도 사본은지도의 복사본이 하나의 배열 목록을 복사하기 때문에 발생합니다 다른지도로 매핑 :

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); 
} 

위 코드에서 새 목록을 만들지 않습니다. 동일한 목록을 다른지도에 저장하면됩니다.새 목록이 필요하면 코드가 있어야한다 그러므로 그 remindGaps의 항목의 사본 항목이 포함됩니다 gapFused이 코드 후

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); 
} 
0

항목은 동일한 객체 (키 및 값)를 참조합니다. 따라서 하나의 맵에 항목을 추가하거나 제거하면 다른 맵에는 아무런 영향을 미치지 않지만 하나의 맵을 통해 액세스하는 값을 변경하면 다른 맵을 통해 액세스하는 변경 사항이 표시됩니다 (예 : remingGaps.get (1)).) .add ("hello")).

는 새 목록, 기존에 단지 참조하지 않기 때문에 코드에 사용되는 이름 "newList는"혼란

...

0

Map의 값은 ArrayList이기 때문에 당신은 일을 얕은 사본 (새 Map에 첫 번째 Map에있는 것과 동일한 Lists 참조)이 있고 두 번째지도의 목록에 대한 변경 사항이 첫 번째지도에 반영됩니다. 이를 피하려면 새 Map을 만들 때 목록을 전체적으로 만들어야합니다.

관련 문제