PartialOrderedSet extends HashSet<E> { public void addABeforeB(final E a, final E b) { if (!this.allowsABeforeB(a, b)) { throw new IllegalStateException("By transitivity " + a + " before " + b + "isn't allowed."); } if (!this.contains(a)) { this.add(a); } if (!this.contains(b)) { this.add(b); } Set<E> directlyAfterA = this.order.computeIfAbsent(a, k -> new HashSet<>()); directlyAfterA.add(b); } PartialOrderedSet(final PartialOrderedSet<E> original);  PartialOrderedSet(); void addABeforeB(final E a, final E b); void requireABeforeB(final E a, final E b); boolean allowsABeforeB(final E a, final E b); Map<E, Set<E>> getOrder(); boolean isADirectlyBeforeB(final E a, final E b); Set<E> getTransitiveClosure(final E e); Set<E> getTransitiveClosure(final Set<E> subSet); boolean isReflexive(); List<E> getTotalOrder(); void merge(final PartialOrderedSet<? extends E> set); void addAll(final PartialOrderedSet<? extends E> set); @Override String toString(); List<E> getLinearization(); @Override Iterator<E> iterator(); @Override void clear(); @Override boolean removeAll(final Collection<?> c); @Override boolean retainAll(final Collection<?> c); @Override boolean removeIf(final Predicate<? super E> filter); @Override boolean remove(final Object e); @Override int hashCode(); @SuppressWarnings("rawtypes") @Override boolean equals(final Object obj);  }
@Test(expected = IllegalStateException.class) public void testAddABeforeB() { String e = "e"; this.set.addABeforeB(A, e); this.set.addABeforeB(e, B); assertTrue("Since a before e was added, this should also be allowed.", this.set.allowsABeforeB(A, e)); assertTrue("Since e before b was added, this should also be allowed.", this.set.allowsABeforeB(e, B)); assertTrue("Since e before b was added, this should also be allowed.", this.set.allowsABeforeB(e, C)); assertTrue("Since e before b was added, this should also be allowed.", this.set.allowsABeforeB(e, D)); this.set.addABeforeB(C, e); }