DefaultId implements Id { @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || !(obj instanceof DefaultId)) return false; DefaultId other = (DefaultId) obj; return name.equals(other.name) && tags.equals(other.tags); } DefaultId(String name);   DefaultId(String name, TagSet tags); @Override String name(); @Override Iterable<Tag> tags(); @Override DefaultId withTag(Tag tag); @Override DefaultId withTag(String key, String value); @Override DefaultId withTags(Tag... ts); @Override DefaultId withTags(Iterable<Tag> ts); @Override DefaultId withTags(Map<String, String> ts); @Override boolean equals(Object obj); @Override int hashCode(); @Override String toString();  }
@Test public void testEquals() { Id id1 = new DefaultId("name").withTag(new BasicTag("k1", "v1")).withTag( new BasicTag("k2", "v2")); Tag[] tags = new Tag[] { new BasicTag("k2", "v2"), new BasicTag("k1", "v1") }; Id id2 = new DefaultId("name").withTags(tags); System.out.println(id1); Assert.assertTrue(id1.equals(id2)); Assert.assertEquals(id1, id2); Assert.assertEquals(id1.hashCode(), id2.hashCode()); }