Skip to content

Functional programming with Boon

RichardHightower edited this page Feb 27, 2014 · 3 revisions

Boon Home | Boon Source | If you are new to boon, you might want to start here. Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!

Java Boon - Functional programming in JDK 1.7 with boon

Functional programming with Boon. Boon adds this to Java JDK 1.7.####

You can do reflection based filters or regular Predicate filters.

        List<Employee> list = list( new Employee("Bob"), new Employee("Sally") );
        setListProperty( list, "salary", 200 );
        list.addAll(Lists.list(new Employee("Rick"), new Employee("Joe")));

        //Reflection
        List<Employee> filtered = filterBy(list, new Object() {
            boolean t(Employee e) { return e.salary>150; }
        });


        ...

         //Predicate based
         List<Employee> filtered = filterBy(list, new Predicate<Employee>() {
                    @Override
                    public boolean test(Employee input) {
                        return input.salary > 150;
                    }
         });

My goal is take some previous work that I did with invoke dynamic and make the reflection based predicate faster than the Predicate interface.

You can also filter with static or non-static methods

        List<Employee> filtered = filterBy(list, ListsTest.class, "filterBySalary");
        ...

        List<Employee> filtered = filterBy(list, this, "filterBySalaryMethod");

Also don't forget that Boon ships with a full in-memory query engine that is actually faster than the predicate based filters.

      List<Employee> filtered = query( list, gt("salary", 150) );

Learn more about the Boon data repo here:

http://rick-hightower.blogspot.com/2013/11/what-if-java-collections-and-java.html

But I digress back to functional framework:

The usual suspects are here:

        ...

        //Reflection Mapper -- Convert Employee object into HRObject
        List<HRObject> wrap = (List<HRObject>) mapBy(list, new Object() {
           HRObject hr(Employee e) {return new HRObject(e);}
        });

        ...
        //Reflection static or non-static methods
        List<HRObject> wrap = (List<HRObject>) mapBy(list, ListsTest.class, "createHRO" );

        List<HRObject> wrap = (List<HRObject>) mapBy(list, this, "createHROMethod" );

        ...
        //Constructor mapping
        List<Employee> list = list(new Employee("Bob"), new Employee("Sally"));
        List<HRObject> wrap = wrap(HRObject.class, list);
        ...


        //
        List<Employee> list =  list(  new Employee("Bob"), new Employee("Sally"));
        List<HRObject> wrap =  mapBy( list, new Function<Employee, HRObject>() {
            @Override
            public HRObject apply(Employee employee) {
                return new HRObject(employee);
            }
        });

Here is one you don't see much in other Java functional frameworks:

    @Test
    public void reduce() {
      long sum =  (int) reduceBy(Lists.list(1,2,3,4,5,6,7,8), new Object() {
          int sum(int s, int b) {return s+b;}
      });

      boolean ok = sum == 36 || die();
      puts (sum);



      sum =  (long) reduceBy(new Integer[]{1,2,3,4,5,6,7,8}, new Object() {
            long sum(long s, int b) {return s+b;}
      });

      ok &= sum == 36 || die();



      sum =  (long) reduceBy(new int[]{1,2,3,4,5,6,7,8}, new Object() {
            long sum(long s, int b) {return s+b;}
      });

      ok &= sum == 36 || die();


       sum =   (long) reduceBy(Lists.list(1,2,3,4,5,6,7,8), new Reducer<Integer, Integer>() {
            @Override
            public Integer apply(Integer sum, Integer v) {
                return sum == null ? v : sum + v;
            }
        }).longValue();


    }

EasyJava (framework that I wrote as an experiment) had currying and all sorts of wild stuff, so I might port some of that here. Boon is a refined version of EasyJava. EasyJava still has many more features but no tests. Boon has tests and docs. EasyJava was my experiment. Boon is my delivery. I might not add currying. Let me know.

Speed

Static reflection 3724 
reflection 3792 
wrap 3900 
java for loop 3286 
anon reflection 3407 
Function 2641 

The anonymous inner class for a function is actually faster than a for loop for the example given. Yeah... it is fast!

 public static void main (String... args) {


        long start;
        long stop;
        List<HRObject> wrap;
        List<Employee> list = Lists.list(new Employee("Bob"), new Employee("Sally"));
        ListsTest obj = new ListsTest();

        for (int index = 0; index < 2_000_000; index++) {

            list.add(new Employee("TEST" + index));
        }


        Object function = new Object() {
            final HRObject hr(Employee e) {return new HRObject(e);}
        };


        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, function);
            fakeCall(wrap);
        }

        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, ListsTest.class, "createHRO" );
            fakeCall(wrap);
        }

        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, obj, "createHROMethod" );
            fakeCall(wrap);
        }

        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, function);
            fakeCall(wrap);
        }







        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
             wrap = (List<HRObject>) Lists.mapBy(list, ListsTest.class, "createHRO" );
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("Static reflection", (stop - start));


        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, obj, "createHROMethod" );
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("reflection", (stop - start));


        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
            wrap = Lists.wrap(HRObject.class, list );
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("wrap", (stop - start));


        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
            wrap = new ArrayList(20);

            for (Employee employee : list) {

                wrap.add(new HRObject(employee));
            }
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("java for loop", (stop - start) );


        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
            wrap = (List<HRObject>) Lists.mapBy(list, function);
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("anon reflection", (stop - start) );



        start = System.currentTimeMillis();
        for (int index = 0; index < 100; index++) {
            wrap =  Lists.mapBy(list, new Function<Employee, HRObject>() {
                @Override
                public HRObject apply(Employee employee) {
                    return new HRObject(employee);
                }
            });
            fakeCall(wrap);
        }
        stop = System.currentTimeMillis();
        puts ("Function", (stop - start) );



    }

Thoughts

Thoughts? Write me at richard high tower AT g mail dot c-o-m (Rick Hightower).

Further Reading:

If you are new to boon start here:

Why Boon?

Easily read in files into lines or a giant string with one method call. Works with files, URLs, class-path, etc. Boon IO support will surprise you how easy it is. Boon has Slice notation for dealing with Strings, Lists, primitive arrays, Tree Maps, etc. If you are from Groovy land, Ruby land, Python land, or whatever land, and you have to use Java then Boon might give you some relief from API bloat. If you are like me, and you like to use Java, then Boon is for you too. Boon lets Java be Java, but adds the missing productive APIs from Python, Ruby, and Groovy. Boon may not be Ruby or Groovy, but its a real Boon to Java development.

Core Boon Philosophy

Core Boon will never have any dependencies. It will always be able to run as a single jar. This is not just NIH, but it is partly. My view of what Java needs is more inline with what Python, Ruby and Groovy provide. Boon is an addition on top of the JVM to make up the difference between the harder to use APIs that come with Java and the types of utilities that are built into Ruby, Python, PHP, Groovy etc. Boon is a Java centric view of those libs. The vision of Boon and the current implementation is really far apart.

===

Contact Info

blog|[twitter](https://twitter.com/RickHigh|[infoq]http://www.infoq.com/author/Rick-Hightower|[stackoverflow](http://stackoverflow.com/users/2876739/rickhigh)|[java lobby](http://java.dzone.com/users/rhightower)|Other | richard high tower AT g mail dot c-o-m (Rick Hightower)|work|cloud|nosql

Clone this wiki locally