Purple Posted January 22, 2016 Share Posted January 22, 2016 Introduction To Predicates What is a Predicate in Java 8? A predicate is a boolean-valued function. In Java 8, it's used primarily for it's functional properties as well as it's ability to result in a true or false statement. This is really useful when you need to filter collections without having to loop over a collection manually as the stream api allows you to also chain predicates. P: X→ {true, false} P being the predicate (value or reference passed in) and X represents the following truth statement resulting in true or false. This might be confusing at first, but I'll show examples later on how this makes sense and why you should use this over the commonly used Filter<T> in OSBot. How is this any better than OSBot's Filter<T> api? We can use predicates to chain logic expressions and filter as many conditions as me need to while keeping our logic nice and clean. We can combine two pedicates where we filter a collection where both condition are met or return the second if the first predicate returns false. Collection of Loaded NPS List<NPC> where we'll be performing our filter final List<NPC> loaded = getNpcs().getAll(); create a list of all loaded npcs in the area Simple Predicate Filtering A Predicate final Predicate<NPC> exists = npc -> npc.exists(); This creates a predicate with the truth statement P(npc) : return true if npc exist Using it inside a stream to filter a collection final NPC getNpcWhere = loaded.stream().filter(exists).findFirst().orElse(null) This will return the first match in the collection that matches the predicate truth statement that returned true or else returns a null NPC object. Chaining Predicates Two Predicates we're going to chain final Predicate<NPC> exists = npc -> npc.exists(); final Predicate<NPC> isAttackable = npc -> npc.exists() && npc.hasAction("Attack") && !npc.isUnderAttack(); Predicate Chain were 2 Predicates return true final NPC getNpcWhere = loaded.stream().filter(exists.and(isAttackable)).findFirst().orElse(null); Here, we're simply chaining preidicates. We're filtering the collection where the the npc exists and it's attackable and if both This or That Predicates Three Predicates we're going to chain final Predicate<NPC> exists = npc -> npc.exists(); final Predicate<NPC> isInteractingLocally = npc -> npc.isInteracting(getPlayers().myPlayer()); final Predicate<NPC> isAttackable = npc -> npc.exists() && npc.hasAction("Attack") && !npc.isUnderAttack(); Alright, this is where the magic happens in a combat script! We can create 1 predicate query that should always return true then either return the second one or the third depending on the second returns true or not. The logic behind this one is that in a combat script, you'd obviously want to return npcs attacking you before you attack a random npc right? So you can achieve this by doing a predicate or function. final NPC getNpcWhere = loaded.stream().filter(exists.and(isInteractingLocally.or(isAttackable))).findFirst().orElse(null); We just made a really advanced logic filter in 1 line of code! That's the power of using Predicates over a generic Filter<T> 9 Quote Link to comment Share on other sites More sharing options...
Vilius Posted January 22, 2016 Share Posted January 22, 2016 Nice Quote Link to comment Share on other sites More sharing options...
Khaleesi Posted January 22, 2016 Share Posted January 22, 2016 You didn't mention anything about execution time, you think it will be faster then a regular Filter? Khaleesi 1 Quote Link to comment Share on other sites More sharing options...
Purple Posted January 22, 2016 Author Share Posted January 22, 2016 You didn't mention anything about execution time, you think it will be faster then a regular Filter? Khaleesi You're right, but we're talking about nano seconds here :P It's not going to make a difference when it comes to RuneScape scripting. However, streams are a little bit slower than iterating over a collection using an iterator, but I'd rather have functionality and clarity of minimal performance when it comes to writing scripts. Some value speed over quality of life. Nice point out though. 1 Quote Link to comment Share on other sites More sharing options...
Khaleesi Posted January 22, 2016 Share Posted January 22, 2016 You're right, but we're talking about nano seconds here It's not going to make a difference when it comes to RuneScape scripting. However, streams are a little bit slower than iterating over a collection using an iterator, but I'd rather have functionality and clarity of minimal performance when it comes to writing scripts. Some value speed over quality of life. Nice point out though. Was just wondering myself ^^ Whenever I wrote my scripts that are currently on the SDN, Predicates didn't exist yet... I could rewrite some points, but I doubt if it has any pros over then just iterating I personally still like to loop through them, maybe I should start using them more and more Khaleesi Quote Link to comment Share on other sites More sharing options...
qverkk Posted January 22, 2016 Share Posted January 22, 2016 good stuff! Quote Link to comment Share on other sites More sharing options...
bazs Posted February 26, 2016 Share Posted February 26, 2016 Thanks for posting this... predicates are so useful. Quote Link to comment Share on other sites More sharing options...