Results 1 to 4 of 4
Like Tree1Likes
  • 1 Post By DarrylBurke

Thread: Java 8 -- Aggregate operations or Aggravating operations

  1. #1
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Java 8 -- Aggregate operations or Aggravating operations

    It used to be so simple (well comparatively so). I was checking out the new Stream operation(s) and the myriad of support functions and came across this beast in the docs for the Collectors (Java Platform SE 8 ) class.

    Java Code:
    static <T,K,D,A,M extends Map<K,D>>      Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier,
                                                                     Supplier<M> mapFactory,
                                                                     Collector<? super T,A,D> downstream)
    I haven't thought much about this but I am sure it has a use somewhere. But for now, it looks like a solution in search of a problem. It will be quite a while before I can say "Hey, I think I'll just use groupingBy."

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  2. #2
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    12,059
    Rep Power
    25

    Default Re: Java 8 -- Aggregate operations or Aggravating operations

    Oh, it's useful. Here's a TreeModel I wrote that in conjunction with a custom JPanel produces a tree on the left and populates a table on the right with data associated with selected nodes in the tree. A checkbox+combobox above the tree allow selection of grouping criteria, and multiple levels of nested grouping is supported. NamedMutableTreeNode is a trivial extension of DefaultMutableTreeNode, with a String field for name with getter and setter.

    Now to make your eyes bleed :)
    Java Code:
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Enumeration;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.TreeMap;
    import java.util.function.Function;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreePath;
    
    public class CollectionGroupTreeModel<T extends Comparable<? super T>>
        extends DefaultTreeModel {
    
      private final List<GroupInfo<T, ? extends Comparable>> groupInfos;
      private int level = -1;
    
      public CollectionGroupTreeModel(Collection<T> collection,
          List<GroupInfo<T, ? extends Comparable>> groupInfos) {
        super(new NamedMutableTreeNode("All", collection));
        this.groupInfos = groupInfos;
        
        if (groupInfos.isEmpty()) {
          ((NamedMutableTreeNode) root).setName("All" + " (" + collection.size() + ")");
        } else {
          int size = groupInfos.size();
          Collector aggregate = Collectors.groupingBy(groupInfos.get(size - 1).grouping);
          for (int i = size - 2; i >= 0; i--) {
            aggregate = Collectors.groupingBy(groupInfos.get(i).grouping,
                aggregate);
          }
          build((NamedMutableTreeNode) root, (Map) collection.stream().collect(aggregate));
        }
      }
    
      private void build(NamedMutableTreeNode parent, Map data) {
        data = new TreeMap(data);
        level++;
        Set<Map.Entry<Comparable, ?>> entries = data.entrySet();
        entries.forEach((entry) -> {
          NamedMutableTreeNode newNode
              = new NamedMutableTreeNode((Map.Entry) entry, groupInfos.get(level).mapping);
          parent.add(newNode);
          if (entry.getValue() instanceof Map) {
            build(newNode, (Map) entry.getValue());
          } else {
            newNode.setName(newNode.getName() + " (" + ((List) entry.getValue()).size() + ")");
            nodeChanged(newNode);
          }
        });
        parent.setName(parent.getName() + " (" + getAllLeafContents(parent).size() + ")");
        level--;
      }
    
      public Collection<T> getAllLeafContents(TreePath... paths) {
        Collection<T> leafContents = new HashSet<>();
        if (paths != null) {
          Arrays.stream(paths)
              .map(TreePath::getLastPathComponent)
              .forEach(node -> addAllLeafContents((NamedMutableTreeNode) node, leafContents));
        }
        return leafContents;
      }
    
      public Collection<T> getAllLeafContents(NamedMutableTreeNode... nodes) {
        Collection<T> leafContents = new HashSet<>();
        Arrays.stream(nodes).forEach(node -> addAllLeafContents(node, leafContents));
        return leafContents;
      }
    
      protected void addAllLeafContents(NamedMutableTreeNode node, Collection<T> leafContents) {
        if (node.isLeaf()) {
          leafContents.addAll((Collection<T>) node.getUserObject());
        } else {
          Enumeration<NamedMutableTreeNode> children = node.children();
          while (children.hasMoreElements()) {
            addAllLeafContents(children.nextElement(), leafContents);
          }
        }
      }
    
      public static class GroupInfo<T, U extends Comparable<? super U>> {
    
        private final String name;
        private final Function<T, U> grouping;
        private final Function<U, String> mapping;
    
        public GroupInfo(String name, Function<T, U> grouping) {
          this(name, grouping, String::valueOf);
        }
    
        public GroupInfo(String name, Function<T, U> grouping, Function<U, String> mapping) {
          this.name = name;
          this.grouping = grouping;
          this.mapping = mapping;
        }
    
        @Override
        public String toString() {
          return name;
        }
      }
    }
    Here's a screenshot:
    Java 8 -- Aggregate operations or Aggravating operations-groupby.gif

    If I'd tried doing this pre-Java 8, I would probably have given up.

    db
    jim829 likes this.
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  3. #3
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    12,059
    Rep Power
    25

    Default Re: Java 8 -- Aggregate operations or Aggravating operations

    And when you're looking at Streams, don't miss the new methods added to CharSequence and Arrays.

    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  4. #4
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Java 8 -- Aggregate operations or Aggravating operations

    Nice example! And I will check out the other methods too.

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

Similar Threads

  1. Java question on operations?
    By runner in forum New To Java
    Replies: 0
    Last Post: 01-26-2014, 10:07 PM
  2. Replies: 0
    Last Post: 10-18-2012, 10:02 AM
  3. Adding order of operations in Java
    By ratyo8 in forum New To Java
    Replies: 1
    Last Post: 01-30-2012, 01:57 AM
  4. Replies: 3
    Last Post: 01-11-2011, 11:45 PM
  5. Replies: 22
    Last Post: 05-08-2008, 12:00 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •