Search code examples
javaalgorithmtreedifference

How to get a difference between two custom trees?


A have the following classes that describe repository of files. There is a server that acts as a main repository and then there are multiple client machines.

class Entry
{
    String name;
    String filename;
    ZonedDateTime lastModified;
}

class Section
{
    String name;
    String directory
    List<Section> sections;
    List<Entry> Entries;
}

Section localRepositoryDescription = scanFilesystem();

Sometimes I need to update client repositories to the latest version. A client sends it's repo's description to the server. In order execute an update, I need to know what files have been updated - get a tree that would contain only updated entries (entryOnServer.lastModified > localEntry.lastModified). I've read about various algorithms to get a difference between two trees, but I am still not sure how to approach this task.

Once I've a got this diff tree, I would compress these modified files to archive and send corresponding responses to clients.


Solution

  • Assuming that you already manage the lastModified property, if in your Entry implements the hashCode()/equals(Object obj) method you can create two Set<Entry>, one in the client one in the server. Then on the server side you can compare the two collections with a code like

    List<Entry> updated = getServerEntries().stream().filter(serverEntry -> {
      return getClientEntries().contains(serverEntry);
    }).collect(Collectors.toList());
    

    Obviously this code assume that the client need to be synchronized based on the server side Set<Entry>, In general the contains method will search first for an Entry using hash then, if it find two equal hashCode, uses equals.

    A simple hashCode could be

      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((filename == null) ? 0 : filename.hashCode());
        result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
      }
    

    The nice part is that you have all this is for free assuming that your app automatically update Entry.lastModified when occurs.