2

次のようなコードのセクションがあります。

            while (scanFile.hasNextLine()) 
            {
                String currentLine = scanFile.nextLine();
                if (currentLine.isEmpty())
                {
                    System.out.println();
                    continue;
                }
                String[] allWordsInCurrentLine = currentLine.split(" ");    

次に、スキャン中のファイルを操作するために使用したい 3 つの方法があります。

最初の方法は、コードの各行を個別にスキャンし、何らかの形式の出力 (pigLatin) を行ごとに出力します (そのため、「while」ループの反復ごとに 1 行の出力が与えられます
。2 番目の方法は、最初にすべてのテキストをスキャンし、さまざまな情報をさまざまな配列と変数に格納します. ユーザーはこの情報を検索できます (そのため, 出力が得られる前に "while" ループ全体が満たされる必要があります). 次に、最初のメソッドと同様のことを行う 3 つ目のメソッドがあります.

コードのこのセクションを再利用する最も効率的な方法を見つけようとしています。もともと、上記のコードの一番下の行の下でメソッド呼び出しを実行しようとしましたが、その上部に for ループがあるため、a==0 の場合、最初のメソッドを呼び出し、次に while ループを介して 2 回目に a がインクリメントされ、次のように、2 番目のメソッドが呼び出されます。

for(String currentWordInCurrentLine : allWordsInCurrentLine)
{
    if (i==0)
        pigLatin(currentWordInCurrentLine);         // Part 1
    if (i==1)
        searchForWord(currentWordInCurrentLine, currentLine);   // Part 2
    if (i==2)
        brailleTranslator();
}

これにはいくつかの問題がありますが、見た目がひどいという事実だけではありません。誰かが私にインターフェイスを試すようにアドバイスしましたが、それらは私のステーションよりも少し上です (コースを始めてまだ数週間しか経っていません)。他に提案はありますか?

編集: pigLatin メソッド呼び出しは、上記の (見栄えは悪いですが) 方法を使用して正常に動作します。ただし、次のメソッドをそのように呼び出すことはできません。動作する前に「while」ループ全体を実行する必要があるためです。

4

2 に答える 2

2

必要な機能を 3 つの異なるプロセスで独自の呼び出し可能クラスにラップし、上記のコードに渡します。この場合、共有コードは次のようになります。

public class FileHandlerManager {

    public static void processFile(File file, List<FileHandler> handlers) {

        // ... Setup your scanFile from your file... leaving this out.

        while (scanFile.hasNextLine()) {

            String currentLine = scanFile.nextLine();

            String[] allWordsInCurrentLine = currentLine.split(" ");

            for (FileHandler handler : handlers) {
                handler.handle(allWordsInCurrentLine);
            }
        }
    }
}

その後、 while loop across の機能を共有できますFileHandler。とはFileHandler? 次のように、非常に簡単に定義します。

public interface FileHandler {
    public void handle(String[] allWordsInCurrentLine);
}

最初のものは次のようになります。

public class PigLatinFileHandler implements FileHandler {
    public void handle(String[] allWordsInCurrentLine) {
        // Do your piglatin code.
    }
}

そして最後に、それを実行するには、次のようにします

public static void main(String[] args) {

    IndexingFileHandler indexHandler = new IndexingFileHandler();

    List<FileHandler> handlers = new LinkedList<FileHandler>();
    handlers.add(new PigLatinFileHandler());
    handlers.add(indexHandler);
    handlers.add(new SimilarToPigLatinFileHandler());

    FileHandlerManager.processFile(file, handlers);

    // Note now you have a reference to indexHandler; so if you wanted to save
    // any state while processing the words you can, and use it here.
}

編集

「より簡単な」オブジェクト指向ではない方法があることを指摘したいだけです。メソッドでファイルを取得し、String[][] を返すことができます。これは、ファイル行の 2 次元配列であり、それらの行の単語で表されます。次に、その配列をハンドラーに渡すことができます。

ただし、このアプローチの欠点は、大きなファイルでは機能しなくなり (すべてを一度にメモリにロードする必要があります)、ファイル全体が読み取られるまで出力が得られないことです。私の答えの(おそらく明らかではない)利点は、ファイルを「ストリーミング」することです。すべてのハンドラーで行を処理してから、その行を破棄し、Java がそのメモリーを再利用できるようにします。このコードを使用すると、10 GB のファイルを処理できますが、そのファイル内の最長の行の長さに等しい Java メモリのみを使用します (さらに、IndexHandler が保存している状態)。

于 2012-11-26T22:19:45.647 に答える
0

1 つの可能性は、次のようにロジックを基本クラスに入れることです。

public class Base {
  public void run() {
    while(...) {
      consume(word);
    }
  }
  protected void consume(string word){
  }
}

次に、ジョブごとにクラスを作成できます。

public PigLatin extends Base {
  protected void consume(string word) {
    // do piggy stuff..
  }
}

次のようにすべてを実行できます。

...
Base l1 = new PigLatin();
l1.run();

Base l2 = new WordSearch();
l2.run();
...

あなたの場合、これを行うのは合理的ではないようです。おそらくコードが複雑になります。でもいい練習になると思います。

このソリューションの欠点は、 を呼び出すたびにファイルを反復処理する必要があることですrun()。異なる実行を分離したい場合は、通常これを行います。これらの実行が互いに干渉しないことが確実な場合は、Cory Kendall のソリューションが最適です。

于 2012-11-26T22:30:32.643 に答える