Data Structures and Algorithms in Java
GitHubAuthor
  • Preface
    • Syllabus
    • Schedule
  • 0. Getting Started
    • 0.1. Environment Setup
    • 0.2. Quiz
  • 1. Java Essentials
    • 1.1. Abstraction
    • 1.2. Implementation
    • 1.3. Unit Testing
    • 1.4. Quiz
  • 2. Priority Queues
    • 2.1. Simple Priority Queues
    • 2.2. Binary Heap
    • 2.3. Unit Testing
    • 2.4. Benchmarking
    • 2.5. Quiz
  • 3. Sorting Algorithms
    • 3.1. Abstraction
    • 3.2. Comparison-based Sort
    • 3.3. Divide & Conquer Sort
    • 3.4. Distribution-based Sort
    • 3.5. Quiz
    • 3.6. Homework
  • 4. Binary Search Trees
    • 4.1. Binary Search Trees
    • 4.2. Balanced BST
    • 4.2. AVL Trees
    • 4.3. Red-Black Trees
    • 4.4. Quiz
  • 5. Tries
    • 5.1. Concept
    • 5.2. Implementation
    • 5.3. Quiz
    • 5.4. Homework
  • 6. Disjoint Sets
    • 6.1. Concept
    • 6.2. Implementation
    • 6.3. Quiz
  • 7. Graphs
    • 7.1. Implementation
    • 7.2. Cycle Detection
    • 7.3. Topological Sorting
    • 7.4. Quiz
  • 8. Minimum Spanning Trees
    • 8.1. Abstraction
    • 8.2. Prim's Algorithm
    • 8.3. Kruskal’s Algorithm
    • 8.4. Edmonds' Algorithm
    • 8.5. Quiz
    • 8.6. Homework
  • 9. Network Flow
    • 9.1. Flow Network
    • 9.2. Ford-Fulkerson Algorithm
    • 9.3. Simplex Algorithm
    • 9.3. Quiz
  • 10. Dynamic Programming
    • 10.1. Fibonacci Sequence
    • 10.2. Tower of Hanoi
    • 10.3. Longest Common Subsequence
    • 10.4. Quiz
Powered by GitBook

©2023 Emory University - All rights reserved

On this page
  • Auxiliary Method
  • Functional Programming
  • Test: Robustness

Was this helpful?

Export as PDF
  1. 2. Priority Queues

2.3. Unit Testing

Robustness tests.

Previous2.2. Binary HeapNext2.4. Benchmarking

Last updated 2 years ago

Was this helpful?

Auxiliary Method

Let us create and define testRobustnessAux() that checks the robustness of any PQ inheriting AbstractPriorityQueue:

/**
 * @param pq   a priority queue.
 * @param keys a list of comparable keys.
 * @param comp a comparator used for sorting.
 */
<T extends Comparable<T>> void testRobustness(AbstractPriorityQueue<T> pq, List<T> keys, Comparator<T> comp) {
    keys.forEach(pq::add);
    keys = keys.stream().sorted(comp).collect(Collectors.toList());
    keys.forEach(key -> assertEquals(key, pq.remove()));
}
  • L6: the generic type T is defined specifically for this method such that the priority queue pq, the list keys, and the comparator comp take the same type T that is comparable.

  • L7: any collection that inherits the interface has the member method that takes a and applies each key in the collection to the consumer.

  • L8: any collection has the member method that returns the of the collection.

    • : creates a stream of the collection whose keys are sorted

    • : creates a collection specified by the .

    • : returns a collector that transforms the stream into a list.

  • L9: iterates each of the sorted keys and compares it to the returned value of pq.remove().

What are the advantages of defining a method-level generic type?

Functional Programming

The following code shows a traditional way of iterating over a list (that is equivalent to L7 above):

for (int i=0; i<keys.size(); i++)
    pq.add(keys.get(i));

Java 5 introduced an enhanced for loop that simplified the traditional for loop:

for (T key : keys)
    pq.add(key);
keys.forEach(key -> pq.add(key));

The syntax of the above code can be simplified as follows (as shown in L7):

keys.forEach(pq::add);

What are the main differences between object-oriented programming and functional programming?

Test: Robustness

Let us define the testRobustness() method that calls the auxiliary method testRobustnessAux():

@Test
public void testRobustness() {
    List<Integer> keys = List.of(4, 1, 3, 2, 5, 6, 8, 3, 4, 7, 5, 9, 7);
    Comparator<Integer> natural = Comparator.naturalOrder();
    Comparator<Integer> reverse = Comparator.reverseOrder();

    testRobustness(new LazyPriorityQueue<>(), keys, reverse);
    testRobustness(new EagerPriorityQueue<>(), keys, reverse);
    testRobustness(new BinaryHeap<>(), keys, reverse);

    testRobustness(new LazyPriorityQueue<>(reverse), keys, natural);
    testRobustness(new EagerPriorityQueue<>(reverse), keys, natural);
    testRobustness(new BinaryHeap<>(reverse), keys, natural);
}
  • L7-9: tests different types of max-PQs. The keys need to be sorted in reverse order for it to test the remove() method.

  • L11-13: tests different types of min-PQs. The keys need to be sorted in the natural order for it to test the remove() method.

The generic types of the PQs in L4-5 are explicitly coded as <Integer>, whereas they are simplified to <> in L7-13. When do generic types need to be explicitly coded?

The testRobustness() method illustrates the benefit of defining AbstractPriorityQueue such that any type of PQ can be passed to testRobustnessAux() for unit-testing.

Java 8 introduced that enabled functional programming in Java. The following code takes each key (as a variable) in keys and applies it to pq.add():

Since Java 8, higher-order methods can be defined by parameterizing types of interfaces in the package.

PriorityQueueTest
Iterable
forEach()
Consumer
stream()
Stream
sorted()
collect()
Collector
toList()
lambda expressions
function