Abstract: In today's puzzle, we want to sort a list of persons. It works in some versions of Java, but not in others. You need to figure out why.
Welcome to the 268th edition of The Java(tm) Specialists' Newsletter. Rain, rain, rain. Our annual rainfall on Crete is about 600mm. From the 24-26 February, over a space of 41 hours, that's how much came down. The most rain fell east of the White Mountains. From there a river gently meanders down through Stilos. Our British friends built a pretty retirement cottage overlooking this river. And I thought our 15000 push-up challenge was of little practical value! My son and I got to carry them out through the rushing river surrounding their house. As I look down towards Tersanas Beach whilst writing this, Crete is back to warm skies with butterflies confirmed that it be spring. Boy did it come down though. I've never seen anything like this in my 47 years.
This newsletter was inspired by a question asked by Igal Sapir during our Data Structures in Java Live Class held in February 2019.
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
Today we want to solve the age-old puzzle: Is a Programmer a Person? Let's define Person as:
public class Person implements Comparable<Person> { private final String name; public Person(String name) { this.name = name; } public int compareTo(Person that) { return name.compareTo(that.name); } public String toString() { return name; } }
Furthermore, let's say that a Programmer is a Person, but that he also
has an IQ of at least 120. Yes, I have been around long enough to know
that this is technically not true, but let's assume that we live in a
perfect world ;-) We also want to say that when comparing the
Programmers, we want the smartest folks (Joshua Bloch, James Gosling,
Brian Goetz) listed before the dumb folks like you and me. We use a
short
to store the IQ. This allows us to compare
them with "iq - that.iq", something forbidden with int
and long
.
public class Programmer extends Person { private final short iq; public Programmer(String name, short iq) { super(name); if (iq < 120) throw new IllegalArgumentException( "Programmer IQ cannot be less than 120"); this.iq = iq; } public int compareTo(Person that) { if (that instanceof Programmer) { Programmer p = (Programmer) that; int result = iq - p.iq; // works because it's a short if (result != 0) return -result; // biggest IQ first } return super.compareTo(that); } public String toString() { return super.toString() + " (" + iq + ")"; } }
Next we want to create a list of persons, where some of these individuals are geeks. A short story about mixing programmers with people. We had a Chania Developers Group. We thought it was a good idea to organize a meetup. It was winter. Not much happens in winter on Crete. We expected a dozen or so geeks to show. Somehow this got onto the local news circuit. Two camera crews showed up from television stations. Newspaper reporters were clamoring to interview us. The coffee shop that we had chosen that night had over a hundred people squashed in. Some were geeks. Others just curious. But the mix did not work. They told us: "Don't come back." Is a Programmer a Person? Let's create them and try and sort them. Note that I do not have much hope. If the sort() fails for whatever reason, such as IncompatiblePersonError, DontBeAWallyError, etc., then we simply try again.
import java.util.*; public class SortCheck { private static final String[] NAMES = { "John", "Paul", "Sarah", "Anton", "Antonia", "Peter", "Heinz", "Kiriaki", "Kirk", "Maurice", "Simone", "Vuyisile", "Prakash", "Yen", "Michelle", "Rabea", "Steve", "Patrick", "Alvaro", "Petros", "Charalambos", "Susie", "Rebekka", "Zoran", "Quinton", "Sean" }; private static final int NUMBER_OF_PERSONS = 10000; public static void main(String... args) { List<Person> persons = new ArrayList<Person>(); for (int i = 0; i < NUMBER_OF_PERSONS; i++) { persons.add(generate()); } while (true) { try { Collections.sort(persons); break; } catch (Throwable e) { System.err.println("Failed - trying again"); } } for (Person person : persons) { System.out.println(person); } } private static final Random RANDOM = new Random(); private static Person generate() { String name = NAMES[RANDOM.nextInt(NAMES.length)]; if (RANDOM.nextBoolean()) { return new Person(name); } else { return new Programmer(name, (short) (RANDOM.nextInt(80) + 120)); } } }
When you run this in Java 6, it works like a charm the first time. In Java 7 it keeps on failing and never recovers. In Java 8 it eventually works.
What gives? Is a Programmer a Person or not? First complete explanation before 2019-03-07T16:00:00 will win a seat on our Data Structures in Java Live Class. (Warning: there are a few subtleties.)
We will discuss this in tomorrow's Happy Hour Webinar, which you are welcome to join for free. We will have Maurice Naftalin join us, author of the most successful book on Java collections (and the least successful ;-))
Kind regards from Crete
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.