### Question:
DefaultId implements Id { DefaultId rollup(Set<String> keys, boolean keep) { if (tags.isEmpty()) { return this; } else { Map<String, String> ts = new TreeMap<>(); for (Tag t : tags) { if (keys.contains(t.key()) == keep && !ts.containsKey(t.key())) { ts.put(t.key(), t.value()); } } return new DefaultId(name, ArrayTagSet.create(ts)); } } DefaultId(String name);   DefaultId(String name, ArrayTagSet tags); @Override String name(); @Override Iterable<Tag> tags(); @Override DefaultId withTag(Tag tag); @Override DefaultId withTag(String key, String value); @Override DefaultId withTags(String... ts); @Override DefaultId withTags(Tag... ts); @Override DefaultId withTags(Iterable<Tag> ts); @Override DefaultId withTags(Map<String, String> ts); @Override String getKey(int i); @Override String getValue(int i); @Override int size(); @Override Id filter(BiPredicate<String, String> predicate); @Override boolean equals(Object obj); @Override int hashCode(); @Override String toString();  }### Answer:
@Test public void testRollup() { Set<String> keys = new HashSet<>(); keys.add("k1"); keys.add("foo"); DefaultId id = (new DefaultId("foo")).withTag("k1", "v1").withTag("k2", "v2"); DefaultId keepId = (new DefaultId("foo")).withTag("k1", "v1"); DefaultId dropId = (new DefaultId("foo")).withTag("k2", "v2"); Assertions.assertEquals(keepId, id.rollup(keys, true)); Assertions.assertEquals(dropId, id.rollup(keys, false)); }