Functionally Filtering a String in Java 8
by Josh Long
I was looking for cleaner ways to filter a string in Java 8. I figured this would be easy as Java has lambdas nicely woven into the APIs, and String instances are already immutable so it seemed like a home-run.
I knew how to do it in a trivial Python example:
#!/usr/bin/env python
print ''.join([a for a in '123 a string !!!' if a.isalpha()])
I asked on Twitter:
“a string !!”.chars().boxed()
— Josh Long (龙之春, जोश) (@starbuxman) March 18, 2017
.filter(c-> isLetter(c))
.map(i -> Character.toString(Character.toChars(i)[0]))
.collect(joining("")) 😞
My initial attempt was valiant, but very complicated. A Java String returns an IntStream from the chars() method, so at some point there has to be a conversion to a Character - this means boxing and unboxing, somewhere.
Others replied suggesting that I use
..a regular expression:
@phillip_webb @starbuxman @java what's wrong with something like
— Ralf D. Müller™ (@RalfDMueller) March 18, 2017
"a string !!".replaceAll("[^a-zA-Z]","")
?
..or Kotlin:
@starbuxman "a string !!".filter(Char::isLetter)
— Hadi Hariri (@hhariri) March 18, 2017
Did I break your Java?
..or the replace method:
@starbuxman You don’t fancy:
— Nicky Mølholm (@moelholm) March 18, 2017
"a string !!".replaceAll("\\W", "")
?
All of these are good ideas, but not quite what I wanted.
I was looking for trivial amounts of conceptual noise - something I could stare at and process, quickly. Maybe Python was the right thing, after all? So I tried embedding Jython (the Python language implementation on the JVM). This required a pesky, um, let's call it utility library (the entire Python language and runtime) whose Maven coordinates are org.python : jython : 2.7.1.b3 :
import org.python.util.PythonInterpreter;
import java.util.Properties;
public class JythonApplication {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put("python.import.site", "false");
PythonInterpreter.initialize(System.getProperties(), properties, new String[0]);
System.out.println(new PythonInterpreter().eval("''.join([a for a in '123 a string !!!' if a.isalpha()])"));
}
}
Not bad! (I'm only kidding. Half kidding, anyway.) Some people liked it, alright? Jeez! :D
@rotnroll666 @phillip_webb
— Josh Long (龙之春, जोश) (@starbuxman) March 18, 2017
System.out.println(new PythonInterpreter().eval("''.join([a for a in '123 a string !!!' if a.isalpha()])")); :D
The following example does a bit less gymnastics than my previous example, and is functional, so I suppose it's the best solution so far. I learned a lot from this example, too.
@phillip_webb @starbuxman Not sure if more clearer but one functional alternative would be pic.twitter.com/RNFOvLSnAi
— Tomche Delev (@tdelev) March 18, 2017
Comments powered by Talkyard.