-4

I'm attempting to create a program that will take a given word and find the list of words that could be made out of the letters inside the given word. Here's my code:

package wordfinder;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class WordFinder {
    public static void main(String[] args) throws IOException {
        List<String> wordList1 = Files.readAllLines(Paths.get("res", "WordList1.txt"));
        List<String> wordList2 = Files.readAllLines(Paths.get("res", "WordList2.txt"));

        Scanner scan = new Scanner(System.in);

        System.out.println("Please enter the string you would like this program to find words in.");
        String wordToFind = scan.nextLine();

        ArrayList<String> words = new ArrayList<>();
        ArrayList<Character> charArray = new ArrayList<>();
        char[] charList = wordToFind.trim().toCharArray();

        for (int i = 0; i < charList.length; i++) {
            charArray.add(charList[i]);
        }

        for (int i = 0; i < wordList1.size(); i++) {
            char[] charsInWordToCheckAgainst = wordList1.get(i).toCharArray();
            ArrayList<Boolean> containsLetter = new ArrayList<>(charsInWordToCheckAgainst.length);

            for (int j = 0; j < charsInWordToCheckAgainst.length; j++) {
                if (charArray.contains(charsInWordToCheckAgainst[j])) {
                    containsLetter.set(j, true);
                }
            }

            if (areAllTrue(containsLetter)) {
                words.add(wordList1.get(i));
            }
        }

        for (int i = 0; i < wordList2.size(); i++) {
            for (int j = 0; j < wordList2.get(i).length(); j++) {
                char[] charsInWordToCheckAgainst = wordList2.get(i).toCharArray();
                ArrayList<Boolean> containsLetter = new ArrayList(charsInWordToCheckAgainst.length);

                for (int k = 0; k < charsInWordToCheckAgainst.length; k++) {
                    if (charArray.contains(charsInWordToCheckAgainst[k])) {
                        containsLetter.set(k, true);
                    }
                }

                if (areAllTrue(containsLetter)) {
                    words.add(wordList2.get(i));
                }
            }
        }

        System.out.println("Words found: " + words.size());

        for(int i = 0; i < words.size(); i++) {
            System.out.println("Word " + i + ": " + words.get(i));

            try {
                TimeUnit.MILLISECONDS.sleep(1);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static boolean areAllTrue(ArrayList<Boolean> bools) {
        for (int i = 0; i < bools.size(); i++) {
            if (!bools.get(i)) {
                return false;
            }
        }

        return true;
    }
}

And here's the error I'm getting:

Please enter the string you would like this program to find words in.
abcdefghijklmnopqrstuvwxyz
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.set(ArrayList.java:444)
    at wordfinder.WordFinder.main(WordFinder.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Process finished with exit code 1

For clarification, WordFinder.java:36 is containsLetter.set(j, true); in the wordList1 for loop. So I really just don't understand why the size of the array is 0. containLetter should not be 0.

UPDATE 1

Updated wordList1 for loop to this:

for (int i = 0; i < wordList2.size(); i++) {
    for (int j = 0; j < wordList2.get(i).length(); j++) {
        char[] charsInWordToCheckAgainst = wordList2.get(i).toCharArray()
        ArrayList<Boolean> containsLetter = new ArrayList<>();
        Collections.fill((List) containsLetter, charsInWordToCheckAgainst.length);

        for (int k = 0; k < charsInWordToCheckAgainst.length; k++) {
            if (charArray.contains(charsInWordToCheckAgainst[k])) {
                containsLetter.set(k, true);
            }
        }

        if (areAllTrue(containsLetter)) {
            words.add(wordList2.get(i));
        }
    }
}

But that still gives me the same error.

1 Answers1

1

According to javadoc for ArrayList constructor new ArrayList<>(charsInWordToCheckAgainst.length) accept single parameter - which is initial capacity of list. Capacity - not size.

The difference is as follow. Size - is number of elements stored in the list. Capacity - is initial array size created for this structure.

E.g. whenever you adding element to list it will check - do I have capacity for it and if not - re-allocate new array. Purpose of providing this parameter into constructor is to reduce amount of re-allocations. In order to pre-fill list - you need to put elements inside manually or use utility functions provided by 3-rd party libraries.

Dmitry
  • 1,233
  • 11
  • 14