Assignment 5 — Collections

Use the library’s set and map to count words. Then build a list of your own out of nodes, and use an iterator to remove from a list without breaking it.

Due Sep 29, 2026

This one has its own repo. Accept it the same way you accepted A4, and clone it. Inside are the finished Matrix from A4, a text file, and two classes that are not finished. WordCount reads the text one word at a time and does nothing with the words yet. WordChain is a list built out of nodes, with the node class and toString written and every other method throwing until you write it.

WordCount reads words.txt from the folder you run in. In IntelliJ that is the project’s root, which is where the file is; if you run from somewhere else, it will not be found.

A floor, if you run out of time. Tasks 1, 3 and 4 are the ones to get working: the words counted, and a chain that can hold and find. Everything else is measured on top of them. Push what you have even if it is only the floor. Partial work you pushed beats finished work you did not.

Task 5 is the one to start early if you can. It is the one where you draw a picture before you type, and that goes badly in a hurry.

Part 1 — the library’s collections

  1. Count the distinct words. In WordCount, put every word the loop hands you into a Set<String>, then print one line:

    142 distinct words

    with your own number in place of 142. The number is size() of the set. A set holds each word once however many times you add it, which is the whole reason to use one here.

    You need java.util.Set and java.util.HashSet.

  2. Name the five commonest. A set cannot count. Make a Map<String, Integer> beside it, and for every word add one to that word’s count. getOrDefault(word, 0) is the method that makes the first time a word appears the same as every other time. Then, after the line above, print the five most frequent words, most frequent first, one per line, the word and then its count with a space between:

    a 11
    of 11

    Two words with the same count come out alphabetically. That rule is what makes your output and ours agree, so keep it.

    A map has no order, so you have to make one. Copy the keys into a list — new ArrayList<>(counts.keySet()) — and sort the list with a comparator of your own, the way you sorted matrices in A4. The comparator needs to see the map to compare two words by their counts, so give it the map in its constructor and keep it in a field.

Part 2 — a list of your own

WordChain is what a LinkedList is made of: a first node, and each node holding one word and a link to the next. The last node’s link is null. The node class is written for you and is private, because nobody outside the chain should ever hold a node.

  1. Write addFirst and size. addFirst makes a new node holding the word, whose next is the old first, and makes it the new first. It always succeeds; a chain may hold the same word twice. size walks the chain and counts.

    Done when three addFirst calls print [owl, dog, cat] in the reverse of the order you made them, and size() says 3.

  2. Write contains. Walk the chain until you find a node whose word equals the one asked for, or run out of nodes.

  3. Write remove. Take out the first node whose word equals the one asked for, and return whether there was one.

    Draw it before you type it. Removing a node means the node before it must point past it, so you walk holding the node before the one you are looking at. The first node has no node before it; that case is separate.

    Done when removing dog from [owl, dog, cat] leaves [owl, cat], removing owl from that leaves [cat], removing elk from anything returns false and changes nothing, and size agrees after each one.

  4. Write get(int index). Walk index links from the front and return the word there. If the chain runs out first, throw IndexOutOfBoundsException — which is what ArrayList.get throws, and what the array did in class on Wednesday.

    This method is why a LinkedList was three thousand times slower than an ArrayList in class. Every get starts again from first.

Part 3 — walking and removing

  1. Prune a list of matrices. Write src/Prune.java with a main that builds a List<Matrix> holding these five, in this order:

    new Matrix(new double[][] {{3, 4}})
    new Matrix(new double[][] {{5, 12}})
    new Matrix(new double[][] {{1, 1}, {1, 1}})
    new Matrix(new double[][] {{9, 9}})
    new Matrix(new double[][] {{-2, 8}})

    then removes every matrix whose magnitude() is above 10 while walking the list with an Iterator, and prints the survivors’ magnitudes on one line with spaces between, then the list’s size() on the next.

    A for loop that calls remove on the list throws ConcurrentModificationException, as it did in class. The iterator’s own remove is the one that works.

Part 4 — say what it does

  1. Give every public method of WordChain a Javadoc block. toString already has one; write the other five in the same shape. Each says what the method returns, remove says what it returns when the word was not there, and get says what it throws.

    A block starts with /** on its own line, ends with */, and sits directly above the method. That is the whole format, and it is what the checker looks for.

Handing in

Commit and push. The last commit before the deadline is what gets marked.

Every push is graded, one check at a time, and the result lands on your feedback pull request — so push early and read what failed, rather than saving it all for the last night.

A student presents this one in class the following Wednesday.