Fingerprinting { private void fingerprintMap(DiagnosingMessageDigestDecorator md, FingerprintingConfig conf, Map<String, Object> map) { map.entrySet().stream() .filter(e -> { if (!conf.getMapAllowList().isEmpty()) { return conf.getMapAllowList().contains(e.getKey()); } else { return !conf.getMapDisallowList().contains(e.getKey()); } }) .sorted(Map.Entry.comparingByKey()) .forEachOrdered(entry -> { md.update(entry.getKey().getBytes()); md.update(fingerprint(entry.getValue(), conf).getBytes()); }); }  @UserFunction @Description("calculate a checksum (md5) over a node or a relationship. This deals gracefully with array properties. Two identical entities do share the same hash.") String fingerprint(@Name("some object") Object thing, @Name(value = "propertyExcludes", defaultValue = "[]") List<String> excludedPropertyKeys); @UserFunction @Description("calculate a checksum (md5) over a node or a relationship. This deals gracefully with array properties. Two identical entities do share the same hash.") String fingerprinting(@Name("some object") Object thing, @Name(value = "conf", defaultValue = "{}") Map<String, Object> conf); @UserFunction @Description("calculate a checksum (md5) over a the full graph. Be aware that this function does use in-memomry datastructures depending on the size of your graph.") String fingerprintGraph(@Name(value = "propertyExcludes", defaultValue = "[]") List<String> excludedPropertyKeys); @Context
    public Transaction tx; @Context
    public Log log; }
@Test public void fingerprintMap() { Map<String, Object> params = map("string", "some string", "boolean", true, "long", 123l, "double", 1234.456d); String hashOfAMap = TestUtil.singleResultFirstColumn(db, "return apoc.hashing.fingerprint($map);", singletonMap("map", params)); assertEquals("040B354004871F76A693DEC2E5DD8F51", hashOfAMap); }