2016-09-06 16 views
0

のようです。はじめに

こんにちは。私は今約2週間問題が発生していると私ははできませんは、それが起こっている理由を見つけることができるようです。 だから、どういう場合ですか?私のプロジェクトのHashetの最大サイズは961

ラフ説明

私は保存したファイルのすべての領域のファイルを読み込み、それらをチェックしのMinecraftツールを、書いています。彼らがプレイヤーが置かれたブロックを持っている場合、そのブロックが入っているチャンクは安全とマークされ、後で削除されません。そうでなければ、いくつかのエンキューが発生するはずであるので、エンキュープロセスが完了した後にチャンクが削除されます。それは私が使用していますHashSetの中に961個の要素に当たるまで

問題

プログラムは、問題なく動作しているようです。 ハッシュセットには、チャンクが安全であるとマークされているかどうかを判断するために使用される文字列が含まれています。 961個の要素があると、メモリがなくなったかのように、それ以上は追加できないように振る舞いますが、実際にはそうではありませんが、2GBのメモリが割り当てられています。私は多くの異なるパラメータで、それを何度もテストしてみたが、HashSetのに要素を追加し、それが961にアップトップス、そしてないよりも、それ以上の追加んが、それはエラーに961

トップスそれ。 RAMも2GBでテストされましたが、運はありません。

コード

ここに私のコードです。それに圧倒されないでください、それはかなり簡単です。

Optionsクラスは、いくつかのオプションをロードするクラスです。言及する価値はありません。

Mainクラス:

public class Main { 

    Options options = new Options(); 
    Deleter deleter; 

    public Main() { 
     deleter = new Deleter(this); 
    } 

    public static void main(String[] args) { 
     Main main = new Main(); 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
      System.out.print("Load world?"); 
      System.out.println("(Y for yes/Q for quit): "); 
      String s = br.readLine(); 
      while (!s.equalsIgnoreCase("Q")) { 
       if (s.equalsIgnoreCase("Y")) { 
        main.deleter.loadWorld(); 
        System.out.println("Enqueue?"); 
        System.out.println("(E for enqueue/Q for quit): "); 
        s = br.readLine(); 
        while (s.equalsIgnoreCase("E")) { // While user wants to enqueue 
         main.deleter.enqueue(); 
         System.out.println("Delete?"); 
         System.out.println("(E for enqueue/D for delete/Q for quit)"); 
         s = br.readLine(); 
        } 
        if (s.equalsIgnoreCase("D")) { 
         main.deleter.delete(); 
        } 

       } 
      } // If input == Quit, do this 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Deleterクラス

public class Deleter { 

    private Options options; 
    private ArrayList<File> files = new ArrayList<>(1000); 
    private HashSet<String> safeChunks = new HashSet<>(20000); 
    private ArrayList<Integer> blockIDsList = new ArrayList<>(100); 
    private int totalChunksEnqueued = 0; 
    private int chunksEnqueued = 0; 

    public Deleter(Main main) { 
     this.options = main.getOptions(); 
     totalChunksEnqueued = 0; 
    } 

    public void loadWorld() { 
     String folderName = options.getSaveFolderFile().getParentFile().getName(); 
     System.out.println("--------Loading world: " + folderName + "--------"); 
     File filesTemp[] = options.getSaveFolderFile().listFiles(); 
     for (File file : filesTemp) { 
      if (file.getName().endsWith("mca")) { 
//    RegionFile regionFile = new RegionFile(file); 
       files.add(file); 
      } 
     } 
     System.out.println("--------World loaded successfully--------"); 
    } 

    public void enqueue() { 
     System.out.println("--------Enqueuing--------"); 
     chunksEnqueued = 0; 
     try { 
      options.reloadConfig(); 
     } catch (FileNotFoundException e2) { 
      e2.printStackTrace(); 
     } 
     int totalFiles = options.getSaveFolderFile().listFiles().length; 
     int counter = 0; 

     //START 

     //Actual enqueuing takes place here 
     for (File file : files) { 
      counter++; 
      System.out.println("Progress: " + counter + "/" + totalFiles + ". Total chunks enqueued: " + totalChunksEnqueued); 
      RegionFile regionFile = new RegionFile(file); 
      for (int chunkX = 0; chunkX < 32; chunkX++) { 
       for (int chunkZ = 0; chunkZ < 32; chunkZ++) { 
        DataInputStream chunk = regionFile.getChunkDataInputStream(chunkX, chunkZ); 
        if (regionFile.hasChunk(chunkX, chunkZ)) { 

         try { 
          Tag root = Tag.readNamedTag(chunk); 

          CompoundTag level = root.getCompound("Level"); 
          ListTag sections = level.getList("Sections"); 

          for (int i = 0; i < sections.size(); i++) { 
           CompoundTag section = (CompoundTag) sections.get(i); 
           byte[] blocksArray = section.getByteArray("Blocks"); 
           byte[] addsArray = section.getByteArray("Add"); 
           byte Y = section.getByte("Y"); 

           boolean worked = false; 
           for (int y = 0; y < 16; y++) { 
            for (int z = 0; z < 16; z++) { 
             for (int x = 0; x < 16; x++) { 
//           int realX = regionX * 32 + chunkX * 16 + x; 
              int realY = Y * 16 + y; 
//           int realZ = regionZ * 32 + chunkZ * 16 + z; 
              if (realY >= minY && realY <= maxY) { 
               // Copied from Chunk Format page. 
               int BlockPos = (y * 16 * 16) + (z * 16) + (x); 
               byte BlockID_a = blocksArray[BlockPos]; 
               short BlockID = BlockID_a; 
               if (addsArray.length != 0) { 
                byte BlockID_b = nibble4(addsArray, BlockPos); 
                BlockID = (short) (BlockID_a + (BlockID_b << 8)); 
               } 
               for (int block : blockIDs) { 
                if (BlockID == block) { 
                 worked = true; 
                 markSafeChunks(regionFile, chunkX, chunkZ, radius); 
                 break; 
                } 

               } 
              } 
              if (worked) 
               break; 

             } 
             if (worked) 
              break; 
            } 
            if (worked) 
             break; 
           } 
           if (worked) 
            break; 
          } 

         } catch (IOException e1) { 
          e1.printStackTrace(); 
         } 
        } 
       } 
      } 

      try { 
       regionFile.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

     } 

     //END 

     System.out.println("Chunks enqueued this time: " + chunksEnqueued); 
     System.out.println("Total chunks enqueued: " + totalChunksEnqueued); 
     System.out.println("--------Finished enqueueing--------"); 
    } 

    public void delete() { 
     System.out.println("--------Deleting--------"); 
     try { 
      options.reloadConfig(); 
     } catch (FileNotFoundException e2) { 
      e2.printStackTrace(); 
     } 
     int totalFiles = options.getSaveFolderFile().listFiles().length; 
     //START 

     // Deletion takes place here 

     for (File file : files) { 
      RegionFile regionFile = new RegionFile(file); 
      // You are now in a region file. 
      counter++; 
      System.out.println("Progress: " + counter + "/" + totalFiles); 
      for (int chunkX = 0; chunkX < 32; chunkX++) { 
       for (int chunkZ = 0; chunkZ < 32; chunkZ++) { 
        if (!safeChunks.contains("" + chunkX + "_" + chunkZ) && regionFile.hasChunk(chunkX, chunkZ)) { 
         try { 
          regionFile.deleteChunk(chunkX, chunkZ); 
          chunksDeleted++; 
         } catch (IOException e1) { 
          e1.printStackTrace(); 
          return; 
         } 

        } 
       } 
      } 
      try { 
       regionFile.close(); 
      } catch (IOException e2) { 
       e2.printStackTrace(); 
      } 
     } 

     //END 

     System.out.println("Chunks deleted: " + chunksDeleted); 
     System.out.println("--------Finished enqueueing--------"); 

    } 

    private synchronized void markSafeChunks(RegionFile regionFile, int chunkX, int chunkZ, int radius) { 
     if (radius == 0) 
      safeChunks.add("" + chunkX + "_" + chunkZ); 
     else 
      for (int surX = chunkX - radius; surX <= chunkX + radius; surX++) { 
       for (int surZ = chunkZ - radius; surZ <= chunkZ + radius; surZ++) { 
        boolean b = surX > chunkX/32 && surX < chunkX/32 + 32; 
        b &= surZ > chunkZ/32 && surZ < chunkZ/32 + 32; 
        if (b && regionFile.hasChunk(surX, surZ) && !safeChunks.contains("" + surX + "_" + surZ)) { 
         safeChunks.add("" + surX + "_" + surZ); 
         chunksEnqueued++; 
         totalChunksEnqueued++; 
        } 

       } 
      } 
    } 

この961天井の問題が起こっている理由を任意のアイデア?

+0

デバッグのヘルプを求める質問( '**なぜこのコードは動作しませんか?** ')には、目的の動作、特定の問題またはエラー、およびそれを再現するのに必要な最短コード**が質問自体に含まれている必要があります**。 **明確な問題文**のない質問は他の読者には役に立たない。参照:[最小限で完全で検証可能なサンプルの作成方法](http://stackoverflow.com/help/mcve) – Biffen

+0

コードには、HashSetへの参照はありません。また、961個の要素の後ろに追加しようとしている値がHashSetにすでに含まれているかどうかを確認してください。 – 11thdimension

+0

@ 11thdimension **実際にはDeleterクラスのHashSetへの参照があり、追加する前にそのHashSetに値が含まれているかどうかチェックします。 – Lazini

答えて

0

HashSetの容量は常に2の累乗で、10億以上の要素を追加できます。しかし、重複は無視されますので、要素を追加したままにしておけば、それらの要素はすでにセットに入っていますが、サイズは増加しません。

OutOfMemoryErrorを取得していない場合、メモリが不足していません。

BTW複数のループから抜け出す簡単な方法は、ラベルを使用することです。

outer: 
while (something) 
    while (nested) 
     while (moreNested) { 
     // 
     if (condition) 
      break outer; 
     } 

これは、working変数を必要としないことを意味します。

+1

コード提案に感謝します。私はすでにそれを使用しています!私が実際に**同じキーを繰り返し誤って追加していたようです。 ***私はそれをクリアするために多くのおかげで***!*** – Lazini