Filtering a list of strings

manu3d

Active Member
Contributor
Architecture
I need to filter a list of strings according to arbitrary criterias. I therefore would like to pass some kind of a filter instance to a constructor so that it can be reused without re-instantiating it on a per-frame basis.

Right now I'm thinking of just writing a simple interface with a filter(trovemap) method and then write a few implementations whose instance I'd pass to the constructor. I was wondering however if here in Terasology there is something along these lines already in use. Or if java has something like that out of the box.

Thoughts?
 

msteiger

Active Member
Contributor
World
Architecture
Logistics
You could try using predicates (Java8 has Predicate<T>, guava has the same for Java7 and below) which return true/false for any T you give them. Predicate can be "implemented" by lambda expressions.
If you are working with Collection<T>, you can transform into a stream, filter it with such a Predicate and transform it back into another collection.
Alternatively, guava's Collections2 helper class provides a filter methods for Collection directly.

Haven't tried it, but this should work:

List<String> list = Lists.newArrayList("Abba", "Zappa");
filtered = Collections2.filter(list, e -> e.startsWith("A"));
 

prestidigitator

New Member
Contributor
Yeah. And to keep a reference to an instantiated predicate from that lambda, you could do:

Code:
java.util.function.Predicate<String> filter = e -> e.startsWith("A");
...though if the same line of code is executed multiple times and no closures are needed, you'll actually get the same object anyway (Java can do this because lambdas have no state). For example:

Code:
public class Test
{
   public static void main(String[] args) {
      Runnable a = create();
      Runnable b = create();

      if (a == b) {
         System.out.println("Same object");  // <- Yes
      } else {
         System.out.println("Different objects");
      }
   }

   private static Runnable create() {
      return () -> System.out.println("Hello");
   }
}

At least that's what my version of OpenJDK 8 does. With closures you have to get different objects:

Code:
public class Test
{
   public static void main(String[] args) {
      Runnable a = create("Jim");
      Runnable b = create("Bob");

      if (a == b) {
         System.out.println("Same object");
      } else {
         System.out.println("Different objects");  // <- Yes
      }
   }

   private static Runnable create(String name) {
      return () -> System.out.println("Hello" + name);
   }
}
 
Last edited:

manu3d

Active Member
Contributor
Architecture
Thank you @msteiger and @prestidigitator for the replies. As I went through them I realized I don't need a new (filtered) collection back from the filtering process. Rather, positively filtered items need to be further processed and added to a string. From your replies I can definitely see a number of options. Let's see what I come up with. Thank you again!
 

prestidigitator

New Member
Contributor
Sounds like a perfect application of the streams API. Something like:

Code:
String result =
   stringList.stream()
      .filter(s -> s.startsWith("A"))
      .map(String::toLowerCase),
      .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
      .toString();
Fun stuff. Almost like adding Python's generator expressions to Java. Anyway, have fun with it. :)
 

manu3d

Active Member
Contributor
Architecture
@prestidigitator: thank you for the further input. My "list of strings" is actually a trove map. This was somewhat covertly mentioned in my original post and I did not emphasize it enough. To use .stream() I'd have to first convert the trove map into an actual list of strings and then process it as you suggest.
 

prestidigitator

New Member
Contributor
@manu3d - Sure. It was just an example. Streams can be built from all kinds of things. For example, you can use Stream.generate() to create an infinite stream, or use StreamSupport.stream() with a custom Spliterator that allows either sequential or parallel processing of elements from any source. Nothing that can't be done with traditional control structures and/or threads, of course. I just find that streams make for nicely condensed, readable, and very flexible logic. And they're fun to play with, too. ;)
 
Top