import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class StringTest {
   
   public static void main(String[] args) {

      File file = new File("shakespeare.txt");
      
      String text = null;

      StopWatch overallWatch = new StopWatch();
      StopWatch loadWatch = new StopWatch();
      try {
         byte[] fileBytes = new byte[(int) file.length()];
         InputStream stream = new FileInputStream(file);
         stream.read(fileBytes);
         text = new String(fileBytes);
         stream.close();
      } catch (IOException e) {
         e.printStackTrace();
      }

      System.out.format("time to load file: %6s seconds\n", loadWatch.seconds());

      runCharIterateTest(text);
      runWordFindTest(text);
      runWordReplaceTest(text);
      String[] splitWords = runWordSplitTest(text);
      runConcatenateTest(splitWords);
      runWordSortTest(splitWords);

      System.out.format("overall test duration: %6s seconds\n", overallWatch.seconds());
   }

   private static void runCharIterateTest(CharSequence text) {
      StopWatch watch = new StopWatch();
      int spaceCount = 0;
      for (int i = 0; i < text.length(); i++) {
        if (text.charAt(i) == ' ') spaceCount++;
      }
      System.out.format("iterated through %s characters, and found %s spaces in %6s seconds\n", text.length(), spaceCount, watch.seconds());
   }

   private static void runWordFindTest(String text) {
      StopWatch watch = new StopWatch();
      int wordInstanceCount = -1;
      int position = 0;
      do {
         wordInstanceCount++;
         position = text.indexOf("the", position + 1);
      } while (position >= 0);
      System.out.format("String.indexOf(): found %s instances of 'the' in %6s seconds\n", wordInstanceCount, watch.seconds());
   }

   private static void runWordReplaceTest(String text) {
      int oldLength = text.length();
      StopWatch watch = new StopWatch();
      String replaced = text.replace("the", "XXXX");
      int newLength = replaced.length();
      int replacementCount = newLength - oldLength;
      System.out.format("replaced %s instances of 'the' with 'XXXX' in %6s seconds\n", replacementCount, watch.seconds());
   }
   
   private static String[] runWordSplitTest(String text) {
      StopWatch watch = new StopWatch();
      String[] splitWords = text.split(" ");
      System.out.format("split text into %s words in %6s seconds\n", splitWords.length, watch.seconds());
      return splitWords;
   }

   private static void runConcatenateTest(String[] splitWords) {
      StopWatch watch = new StopWatch();
      StringBuilder builder = new StringBuilder();
      for (String word : splitWords) {
         builder.append(word);
         builder.append(" ");
      }
      String rebuilt = builder.toString();
      System.out.format("concatenated %s words (with %s chars) in %6s seconds\n", splitWords.length, rebuilt.length(), watch.seconds());
   }

   private static void runWordSortTest(String[] words) {
      List<String> wordList = new ArrayList<String>();
      wordList.addAll(Arrays.asList(words));
      StopWatch watch = new StopWatch();
      Collections.sort(wordList, String.CASE_INSENSITIVE_ORDER);
      System.out.format("sorted %s words, ignoring case, in %6s seconds\n", words.length, watch.seconds());
   }

   private static class StopWatch {
      private long startNanos;
      public StopWatch() { this.startNanos = System.nanoTime(); }
      public double seconds() {
         return (System.nanoTime() - startNanos) / 1000000000.0;
      }
   }

}
