Jump to content
Frequently Asked Questions
  • Are you not able to open the client? Try following our getting started guide
  • Still not working? Try downloading and running JarFix
  • Help! My bot doesn't do anything! Enable fresh start in client settings and restart the client
  • How to purchase with PayPal/OSRS/Crypto gold? You can purchase vouchers from other users
  • Try asking for help in the chatbox
  • Using Lambdas in Java 8.


    Notorious
     Share

    Recommended Posts

    Alright, though I won't being going into great detail about what Lambdas are, I will be showing everyone how useful lambdas are, and how they make the writers life easier.

     

    The holy:

    00702257d7.png

     
    So technically a lambda expression is defined as:
     

    A lambda expression is an anonymous function that you can use to create delegates or expression tree types. By using lambda expressions, you can write local functions that can be passed as arguments or returned as the value of function calls.

     

    A quick example of a lambda in Java would be parameters, the -> arrow, and an expression.

     

    For example: (Object object) -> { object.toString(); }

     

    If that definition confused you, don't worry it is very vague, and hopefully after a few examples it will make much more sense!

     

    The parts I covered and plan to cover:

    • When and Where to use Lambdas
    • Basics of the Foreach loop.
    • Basics of Method References
    • Basic of Stream Filters

    If there is anything I didn't cover, and you would like to see added, please let me know! :D

     

    Color Key:

    Finished

    Working

    Haven't Started

     

    When and Where to use Lambdas:

     

     

    Well believe it or not, using a lambdas seem much more confusing that they really are. So lets start with a basic example, lets look at a implementation. Below, we see how we could create a object with implementable methods. In Java 7 and before it looks like:

    Runnable runnable = new Runnable() {
       public void run() {
           //I'm inside the run method.
       }
    };
    

    Now, when we create this runnable object, we must also implement the run() method as well inside of the block. Though since the runnable object is already expecting a particular type, we could use lambdas to pass a generic reference which will save us some lines of code. So now the method above, can look similar to this:

    Runnable s = () -> {
         //I'm inside the run method.
    };
    

    Also if we look a EventHandler, such as:

    JButton jButton = new JButton();
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                 //Action stuff here       
             }
    });
    

    As you can see, we need a parameter for the implemented method actionPerformed, so to do this for a lambda expression, we simply add a reference to the opening of the expression, for example:

    JButton jButton = new JButton();
    jButton.addActionListener(e -> {
         //"e" is a ActionEvent reference
         //Action stuff here       
    });
    

     


     
    The Basics of the Java 8 Foreach Loop:


     
    So now lets start one something that I most commonly use, the foreach loop. This method has now been integrated inside of java.util.List and java.util.Iterable. As well as some other cool features I will talk about more later.
     
    So let's see the difference between using and not using lambdas.
    First we have a normal java.util.List and iterate that list through a for loop printing each value.

    The original type of for loop, the Indexed Loop:

    L: {
    List<Object> list = new ArrayList<>();
         //Indexed for loop
         for(int i = 0; i < list.size(); i++){
              System.out.println(list.get(i));    
         }
    }
    

    The for each loop which was introduced in JDK 1.5.0:

    L: {
    List<Object> list = new ArrayList<>();
         //Foreach loop
         for(Object o : list){
              System.out.println(o);    
         }
    }
    

    So let's move on to using lambdas...
    Now I'll show you how to achieve the same thing as the two loops above, just with less typing:
     

    L: {       
            List<Object> list = new ArrayList<>();
            list.forEach(o -> System.out.println(o));
    }
    

    For a lambda expression with multiple lines, we use a curly brace after the opening " -> " so that we may use more than one line.

    L: {       
            List<Object> list = new ArrayList<>();
            list.forEach(o -> {
                System.out.println(o);
                //More lines go here
            });
    }
    

    Example 0.1:
    1dc825e34b.png
     
    Example 0.2:
    41e0b77d50.png


     
    The Basics of Method References:


    So to start off, we are going to use one of the examples used in the last section.

    L: {       
            List<Object> list = new ArrayList<>();
            list.forEach(o -> {
                System.out.println(o);
            });
    }
    

    Though I didn't mention this above, though this method can be simplified much more. As you notice we only handle one action inside of this loop, and that action being println. So how can we simplify it you may ask, and my answer is using a method reference.
     
    A method reference usually will look similar to:

    //Static
    ClassName::methodName
    //Local
    objectName::methodName
    

    So let's use the example above, and simplify it using a method reference.

    L: {
            List<Object> list = new ArrayList<>();
            list.forEach(System.out::println);
    }
    

    Since the println method is static, and is inside of System.out, we can use a reference. And please note, that the output acquired from this, will match the other examples above, just with less lines of code! :D
    Though before I leave this topic, let me show you a quick example of how to use a local version of a reference by using the remove method inside of the list we created:

    L: {
           List<Object> list = new ArrayList<>();
           list.forEach(list::remove);
    }
    

    Now this list, will remove all objects that are iterated through, so pretty much this will remove all objects in the list.


     
    The Basics of Stream Filters:

     

    So now let's discuss another one of my newly favorite features added in Java 8. And that would be the java.util.Stream class. Honestly the more I use this class, the more uses I find for it!

     

    So let's start with original foreach loop (Java 7 and before) that has added null check, before using the variable.

    L: {
        List<Object> list = new ArrayList<>();
        //Foreach loop
        for(Object o : list){
            if(o != null){
                useObject(o);  
            }  
        }
    }
    

    Now let's simply this expression using the java.util.Stream class:

    L: {
          List<Object> list = new ArrayList<>();
          //Foreach loop
          list.stream().filter(o -> o != null).forEach(o -> {
                useObject(o);
          });
    }
    

    Now let's combine our result of adding the filter, then take it one step further, and add a method reference. Since the method useObject(Object) is local, we can reference the method by using "this::useObject", like so:

    L: {
           List<Object> list = new ArrayList<>();
            //Foreach loop
            list.stream().filter(o -> o != null).forEach(list::remove);
    }
    

    So as you can see, first we call List then stream(), then we use the filter method inside of Stream. This method, will remove any object that doesn't match the criteria (Not permanently delete, just from the outputted list), then we simply just iterate through the output list using a forEach.

     

     

    Link to comment
    Share on other sites

    The for each loop which was introduced in JDK 1.5.0: is called an enhanced for loop

     

    Yee they also go by for each as Eliot was saying.

    Like in this documentation from Oracle, they call it a for-each loop:

    http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

     

    Here is how the example looks with the for-each construct:

    void cancelAll(Collection<TimerTask> c) {
        for (TimerTask t : c)
            t.cancel();
    }
    

    But your right, I have heard it called enhanced for loop!

    Link to comment
    Share on other sites

    • 2 years later...

    You can also reference methods of the consumed instance:

    List<Player> players = ...;
    players.forEach(Player::update); //not referencing static method
    
    class Player {
        public void update() { }
    }
    

    Since the consumed instances are Player objects, and Player has a method with no parameters, we can reference that method.

     

    You can also reference a constructor:

    Supplier<Object> object = Object::new;
    
    Edited by Dioxin
    Link to comment
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now
     Share

    ×
    ×
    • Create New...

    Important Information

    We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.