DEV Community

Cover image for The Difference Between `-able` and `-tor` in Java: My Visualization
Yoshi
Yoshi

Posted on

The Difference Between `-able` and `-tor` in Java: My Visualization

When I first encountered Java interfaces like Iterable/Iterator and Comparable/Comparator, I was thoroughly confused. The reason? The suffixes -able and -tor threw me off. Despite their similar naming conventions, their design philosophies were quite different.

I initially assumed that XXX-able would always correspond to some kind of XXX-tor, with the latter providing methods that supported the former. This led me to believe that Iterator existed purely to implement the methods defined by Iterable. However, when I came across Comparable, I was confused: "Wait, what’s Comparator for, then?"

To clear up this confusion, I organized my thoughts and am sharing them here.

-able Is an Interface, but What About -tor?

In Java, Iterable and Comparable are both interfaces.

When a class implements these interfaces, it must include the methods specified by the interface.

For example, in the case of Iterable, the required method is iterator(), which returns an object that implements the Iterator interface. And yes, Iterator itself is also an interface, which means it defines its own required methods: hasNext() and next().

Similarly, Comparable is an interface that requires implementing the compareTo() method. Meanwhile, Comparator is another interface, with its own required method, compare(). Both Comparable and Comparator are used to define comparison logic, but there is an important difference:

  • Comparable defines a "natural order" for a class.
  • Comparator, on the other hand, is used to define custom comparison logic without modifying the class itself.

Comparison of Comparable and Comparator

Feature Comparable Comparator
Purpose Defines natural ordering within the class itself Defines alternative ordering without modifying the class
Implementation Implemented directly in the class Implemented in a separate class
Key Method compareTo() compare()
Import Requirement No explicit import needed Requires importing Comparator

Understanding Through Illustrations

The confusion arose because the design philosophies behind interfaces for iteration and comparison differ. To better understand, I created some illustrations to visualize these concepts.

difference-between-interaction-and-comparison

In the Case of Iteration

An Iterator is a mechanism equipped with a "Next" button and an "is-empty" check, designed for iteration processing. At least one standard iteration logic must be defined. If necessary, it is also possible to have multiple versions with different names and custom logic.

Meanwhile, Iterable acts as the manager for the standard iteration mechanism. Thanks to Iterable, when called in a for-loop, the default iteration logic is implicitly used. Custom Iterator objects created with different iteration logic lack such an Iterable manager, so looping requires explicitly calling hasNext() and next().

In the Case of Comparison

Comparable is like attaching a tag for the default sorting criteria. On the other hand, Comparator is responsible for attaching tags for alternative sorting criteria. Based on these sorting tags, methods like compareTo() or compare() determine the relative order of objects. This evaluation is then utilized in other processes like sorting.

Understanding the distinction between -able and -tor involves recognizing that both Iterable and Comparable provide standards—Iterable for iteration and Comparable for default comparison criteria.

What Happens If You Implement Iterator Directly?

What if we skip Iterable and directly implement hasNext() and next()?

In this case, we wouldn't be constrained by the method names defined in the interface. This allows for adding custom methods like reset() to build iteration logic tailored for specific use cases.

However, the drawback is that without implementing Iterable, your class won't be compatible with Java's standard collections API. This means you lose the ability to seamlessly use Java's built-in tools and methods. For example:

  • You can't use enhanced for-each loops.
  • Utility methods from the Collections class, such as min, max, or sort, won't work with your custom class.

To maintain compatibility with standard APIs and ensure versatility, it's crucial to implement Iterable.

It’s worth noting that Iterable only requires the iterator() method to be implemented. If you decide to implement a custom iterator, in practice, the process is similar to directly implementing Iterator. You'll still need to explicitly call Iterator methods for loop processing.

// Reverse iteration: explicitly using a reverseIterator()
Iterator<String> reverseIterator = collection.reverseIterator();
while (reverseIterator.hasNext()) {
    System.out.println(reverseIterator.next());
}
Enter fullscreen mode Exit fullscreen mode

Summary of Design Intentions

In the Case of Iterable / Iterator

  • Clear Separation of Responsibilities
    • Iterable defines the capability of being iterable ("able to be iterated over").
    • Iterator provides the mechanism for "how to execute the iteration."
  • Focus on Fundamental Functionality Over Flexibility
    • Iterable and Iterator are designed with the assumption of having a single iteration criterion and are not intended to support multiple iteration criteria.

In the Case of Comparable / Comparator

  • Flexible Comparison Criteria
    • By combining the default ordering provided by Comparable and custom ordering via Comparator, they offer flexibility as needed.
  • Emphasis on Independence
    • Comparable embeds the natural ordering directly within the class, whereas Comparator is defined externally, allowing it to be used without modifying the class.

I hope this article is helpful to anyone looking to better understand these concepts.

Reference Links

Top comments (0)