Function chaining in Java - java

I need to do a lot of different preprocessing of some text data, the preprocessing consists of several simple regex functions all written in class Filters that all take in a String and returns the formatted String. Up until now, in the different classes that needed some preprocessing, I created a new function where I had a bunch of calls to Filters, they would look something like this:
private static String filter(String text) {
text = Filters.removeURL(text);
text = Filters.removeEmoticons(text);
text = Filters.removeRepeatedWhitespace(text);
....
return text;
}
Since this is very repetitive (I would call about 90% same functions, but 2-3 would be different for each class), I wonder if there are some better ways of doing this, in Python you can for example put function in a list and iterate over that, calling each function, I realize this is not possible in Java, so what is the best way of doing this in Java?
I was thinking of maybe defining an enum with a value for each function and then call a main function in Filters with array of enums with the functions I want to run, something like this:
enum Filter {
REMOVE_URL, REMOVE_EMOTICONS, REMOVE_REPEATED_WHITESPACE
}
public static String filter(String text, Filter... filters) {
for(Filter filter: filters) {
switch (filter) {
case REMOVE_URL:
text = removeURL(text);
break;
case REMOVE_EMOTICONS:
text = removeEmoticons(text);
break;
}
}
return text;
}
And then instead of defining functions like shown at the top, I could instead simply call:
filter("some text", Filter.REMOVE_URL, Filter.REMOVE_EMOTICONS, Filter.REMOVE_REPEATED_WHITESPACE);
Are there any better ways to go about this?

Given that you already implemented your Filters utility class you can easily define a list of filter functions
List<Function<String,String>> filterList = new ArrayList<>();
filterList.add(Filters::removeUrl);
filterList.add(Filters::removeRepeatedWhitespace);
...
and then evaluate:
String text = ...
for (Function<String,String> f : filterList)
text = f.apply(text);
A variation of this, even easier to handle:
Define
public static String filter(String text, Function<String,String>... filters)
{
for (Function<String,String> f : filters)
text = f.apply(text);
return text;
}
and then use
String text = ...
text = filter(text, Filters::removeUrl, Filters::removeRepeatedWhitespace);

You could do this in Java 8 pretty easily as #tobias_k said, but even without that you could do something like this:
public class FunctionExample {
public interface FilterFunction {
String apply(String text);
}
public static class RemoveSpaces implements FilterFunction {
public String apply(String text) {
return text.replaceAll("\\s+", "");
}
}
public static class LowerCase implements FilterFunction {
public String apply(String text) {
return text.toLowerCase();
}
}
static String filter(String text, FilterFunction...filters) {
for (FilterFunction fn : filters) {
text = fn.apply(text);
}
return text;
}
static FilterFunction LOWERCASE_FILTER = new LowerCase();
static FilterFunction REMOVE_SPACES_FILTER = new RemoveSpaces();
public static void main(String[] args) {
String s = "Some Text";
System.out.println(filter(s, LOWERCASE_FILTER, REMOVE_SPACES_FILTER));
}
}

Another way would be to add a method to your enum Filter and implement that method for each of the enum literals. This will also work with earlier versions of Java. This is closest to your current code, and has the effect that you have a defined number of possible filters.
enum Filter {
TRIM {
public String apply(String s) {
return s.trim();
}
},
UPPERCASE {
public String apply(String s) {
return s.toUpperCase();
}
};
public abstract String apply(String s);
}
public static String applyAll(String s, Filter... filters) {
for (Filter f : filters) {
s = f.apply(s);
}
return s;
}
public static void main(String[] args) {
String s = " Hello World ";
System.out.println(applyAll(s, Filter.TRIM, Filter.UPPERCASE));
}
However, if you are using Java 8 you can make your code much more flexible by just using a list of Function<String, String> instead. If you don't like writing Function<String, String> all the time, you could also define your own interface, extending it:
interface Filter extends Function<String, String> {}
You can then define those functions in different ways: With method references, single- and multi-line lambda expressions, anonymous classes, or construct them from other functions:
Filter TRIM = String::trim; // method reference
Filter UPPERCASE = s -> s.toUpperCase(); // one-line lambda
Filter DO_STUFF = (String s) -> { // multi-line lambda
// do more complex stuff
return s + s;
};
Filter MORE_STUFF = new Filter() { // anonymous inner class
// in case you need internal state
public String apply(String s) {
// even more complex calculations
return s.replace("foo", "bar");
};
};
Function<String, String> TRIM_UPPER = TRIM.andThen(UPPERCASE); // chain functions
You can then pass those to the applyAll function just as the enums and apply them one after the other in a loop.

Related

Cleaning up a method call

Given the following code:
String s = "dirty";
for (Action action : actions) {
s = doAction(s, action);
}
...where Actions can be a cleaning operation on the string such as removing illegal chars or removing a duplicate word.
Is there a way to write this more elegantly to handle the call without reassigning the string?
I don't think you can avoid reassigning the string as you need the updated value in each iteration.
As for:
Is there a way to write this more elegantly
Using the streams API, you could do:
String result = actions.stream() // or Arrays.stream(actions)
.reduce("dirty", (s, action ) -> doAction(s, action),
(e, a) -> {throw new RuntimeException("un-implemented");});
Although it's arguably not as readable as your solution.
A recursive way to write it would be something like this:
public static void main(String[] args) {
List<Action> actions = .. //your list of Actions
String s = doActions("dirty", actions);
}
private static String doActions(String s, List<Action> actions) {
if(actions.isEmpty()) {
return s;
} else {
// apply the first Action
Action action = actions.remove(0);
String newString = doAction(s, action);
// recursively call with the new String and the remaining actions
return doActions(newString, actions);
}
}
But as you can see, you still get a string creation/assignement in the doActions method. This is due to the fact that String is immutable and can't be modified.
If you are just looking for a recursive way to write it then that could do. If you really want to get rid of the new String creation, you need to use a StringBuilder, as Jacob G suggested. With a signature such as
void doAction(StringBuilder sb, Action action)
You can avoid reassigning s by making it a field
public class SActions {
private String s;
SActions(String s){this.s = s;}
public void doAction(Action action){ /* apply action to s */}
public String getString() { return s; }
public static void main(String[] args) {
SActions sActions = new SActions("abc");
sActions.doAction(anAction);
System.out.println(sActions.getString());
}
}
You could also add a method to accept a collection of Actions:
public void doAction(Collection<Action> actions) {
for (Action action : actions) {
doAction(action);
}
}
To make the object reusable, add a setter:
public SActions setString(String s) {
this.s = s;
return this;//for convenience, so you can chain invocation
}
Note that the setter return this for more convenient invocation:
SActions sActions = new SActions(); //requiers standard constructor
sActions.setString("abc").doAction(anAction);
If it is more or less elegant' it is certainly arguable.

Guava predicate to filter various conditions without anonymous class or extra classes

With Java 6 and Guava 12.0 I am trying to filter a list of Strings based on if they have a specific prefix or not. Is there a way to do this without using anonymous classes or a separate class for each distinct prefix I want?
This works but it's ugly (even uglier with my company's imposed formatting I've removed).
private String foo(String prefix, List<String> stuff) {
Collection<String> withPrefix = Collections2.filter(stuff, new Predicate<String>() {
#Override
public boolean apply(String input) {
return input.startsWith(prefix);
}
});
//...
}
Of course I could do something like the following.
public class PrefixCheckForAA implements Predicate<String> {
#Override
public boolean apply(String input) {
return input.startsWith("AA");
}
}
public class PrefixCheckForZZ implements Predicate<String> {
#Override
public boolean apply(String input) {
return input.startsWith("ZZ");
}
}
Is there any way to do this without anonymous classes or a bunch of seemingly redundant classes?
I found a solution while writing this, I can't believe I was so silly to not think of this...
Simply make the class have a constructor that requires a String, use this String as the prefix to check for.
public class PrefixChecker implements Predicate<String> {
private final String prefix;
public Prefix(String prefix) {
this.prefix = prefix;
}
#Override
public boolean apply(String input) {
return input.startsWith(prefix);
}
}
While your own solution is perfectly valid, you can slim down your code even further by using Guava library functionality:
Collection<String> withPrefix = Collections2.filter(stuff, Predicates.containsPattern("^AA"));
For a list of all functionality of Predicates, please go here.

Comparing a String to an Object's toString() method dynamically

I'm reading from a text file, like so:
while ((line = br.readLine()) != null) {
String[] a = line.split("\\: ");
key = a[0];
action = a[1];
gameKeys.add(key, action);
}
where the file would be something like
SPACE: FIRE_ACTION
E: USE_ACTION
This part works, key and action are both what I want.
gameKeys is a Map declared like so:
private static Map<Keyboard.Key, Action> gameKeys = new HashMap<>();
Keyboard.Key has fields such as SPACE, A, RETURN, etc.
Action is an interface, that holds other actions; those actions have a toString() method that returns the action, e.g. new FireAction.toString() returns FIRE_ACTION.
Example of an Action:
public class FireAction implements Action {
#Override
public void execute() {
System.out.println("Fire key pressed!");
}
#Override
public String toString() {
return "FIRE_ACTION";
}
}
So, I'm trying to turn the file's components into objects, like if key was "SPACE" and action was "FIRE_ACTION", then, after the add method is performed, gameKeys would have <Keyboard.Key.SPACE, new FireAction()>
Is there anyway I can do this?
You could try this:
Save your Action classes in a Map<String, Class<? extends Action>>
Read the Key -> Action bindings from the file
Resolve the string action to an actual Action object via the map
Example:
public class Main {
private static final Map<Keyboard.Key, Action> gameKeys = new HashMap<>();
private static final Map<String, Class<? extends Action>> actions = new HashMap<>();
static {
actions.put(FireAction.NAME, FireAction.class);
actions.put(WalkAction.NAME, WalkAction.class);
}
public static void main(String[] args) {
// read from file etc.
try {
// e.g. found SPACE : FIRE_ACTION
gameKeys.put(Keyboard.Key.SPACE, actions.get("FIRE_ACTION").newInstance());
// e.g. found A : WALK_ACTION
gameKeys.put(Keyboard.Key.A, actions.get("WALK_ACTION").newInstance());
} catch (IllegalAccessException | InstantiationException ex) {
ex.printStackTrace();
}
}
}
public class FireAction implements Action {
public static final String NAME = "FIRE_ACTION";
#Override
public void execute() {
System.out.println("Fire key pressed!");
}
#Override
public String toString() {
return NAME;
}
}
Sure
Object keyObj = key, actionObj;
if (key.equals("SPACE")) keyObj = Keyboard.Key.SPACE;
if (action.equals("FIRE_ACTION")) actionObj = new FireAction());
You can use a Map<String, ...> as an alternative to using 'if's if you have a lot of cases
You can't achieve what you have asked directly - because then Java would have to create ALL the classes it can create(some have non-default constructors or even private), and call their toString() method (which may have side-effects in general case).
So anyway you'll have to create registry with all actions(preferrable way), or you can try to use reflection to create Actions in runtime.

Decorator in Java

I see about decorator example in Python:
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
#makebold
#makeitalic
def hello():
return "hello world"
print hello() ## returns <b><i>hello world</i></b>
And got some curious how it can be implement in Java, so I search and got some example using Decorator Design Pattern.
public class Main {
public static void main(String[] args) {
Wrapper word = new BoldWrapper(new ItalicWrapper());
// display <b><i>hello world</i></b>
System.out.println(word.make("Hello World"));
}
}
public interface Wrapper {
public String make(String str);
}
public class BoldWrapper implements Wrapper {
private Wrapper wrapper;
public BoldWrapper() {
}
public BoldWrapper(Wrapper wrapper) {
this.wrapper = wrapper;
}
#Override
public String make(String str) {
if(wrapper != null) {
str = wrapper.make(str);
}
return "<b>" + str + "</b>";
}
}
public class ItalicWrapper implements Wrapper {
private Wrapper wrapper;
public ItalicWrapper() {
}
public ItalicWrapper(Wrapper wrapper) {
this.wrapper = wrapper;
}
#Override
public String make(String str) {
if(wrapper != null) {
str = wrapper.make(str);
}
return "<i>" + str + "</i>";
}
}
How do I make this like the Python example above using a Java Annotation like this one:
public class Main {
public static void main(String[] args) {
#BoldWrapper
#ItalicWrapper
String str = "Hello World";
// Display <b><i>Hello World</i></b>
}
}
public #interface BoldWrapper {
public void wrap() default "<b>" + str + "</b>";
}
public #interface ItalicWrapper {
public void wrap() default "<i>" + str + "</i>";
}
I got some problem when I tried to make the sample, the problem is I don't know how I can pass the str value from the main method to the BoldWrapper and ItalicWrapper so it can concatenate and how to return it, so the main method can display the result that has been concatenate.
Please advise if there is something wrong with my understanding of annotation.
If you are particularly interested in doing this kind of stuff with annotations (you don't have to really):
This example should get you started:
public class AnnotationTest
{
#Target( ElementType.METHOD )
#Retention( RetentionPolicy.RUNTIME )
public static #interface TagWrapper
{
public String[] value() default {};
}
public static interface TextFragment
{
public String getText();
}
public static class TagWrapperProcessor
{
public static String getWrapperTextFragment( TextFragment fragment )
{
try
{
Method getText = fragment.getClass().getMethod( "getText" );
TagWrapper tagWrapper = getText.getAnnotation( TagWrapper.class );
String formatString = "<%s>%s</%s>";
String result = ( String ) getText.invoke( fragment );
for ( String tag : tagWrapper.value() )
{
result = String.format( formatString, tag, result, tag );
}
return result;
}
catch ( Exception e )
{
throw new RuntimeException( e );
}
}
}
public static class BoldItalicFragment implements TextFragment
{
private String _text;
public BoldItalicFragment( String text )
{
_text = text;
}
#Override
#TagWrapper(
{
"b", "i"
} )
public String getText()
{
return _text;
}
}
#Test
public void testStuff()
{
System.out.println( TagWrapperProcessor.getWrapperTextFragment( new BoldItalicFragment( "Hello, World!" ) ) ); // prints: <i><b>Hello, World!</b></i>
}
}
This is late but I think it may help the other people. From Java 8 with Function interface, we can write something close to python decorator like this:
Function<Function<String, String>, Function<String, String>> makebold = func -> input -> "<b>" + func.apply(input) + "</b>";
Function<Function<String, String>, Function<String, String>> makeitalic = func -> input -> "<i>" + func.apply(input) + "</i>";
Function<String, String> helloWorld = input -> "hello world";
System.out.println(makebold.apply(makeitalic.apply(helloWorld)).apply("")); // <b><i>hello world</i></b>
1) The link you cited is a good one - it does justice to the "Decorator Pattern" with respect to Java. "Design Patterns" themselves, of course, are independent of any particular OO language:
http://en.wikipedia.org/wiki/Design_Patterns
2) Here is another good link:
When to use the decorator pattern
In Java, a classical example of the decorator pattern is the Java I/O Streams implementation.
FileReader frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);
4) So yes, the "decorator pattern" is a good candidate for this problem.
Personally, I would prefer this kind of solution:
String myHtml =
new BoldText (
new ItalicText (
new HtmlText ("See spot run")));
5) However annotations are also an option. For example:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
Python decorators very like java annotation, but that are very different principle.
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
But you can prosessing class file with bytecode enhancement. I make a simple project for implementing that approach. It using javassist processing class file after building. It searching methods with specified annotation in classes. And add bridge methods for calling between wrapped method and original method. It look like, calling bridgeMethod() -> wrapperMethod() -> originalMethod(). Your can reference from https://github.com/eshizhan/funcwraps.
Although this doesn't resolve how to use annotations as you wanted, rather than using the "decorator design", I could propose you use the "builder design" if it suits better to your needs (it seems like so).
Quick usage example:
public class BuilderPatternExample {
public static void main(String args[]) {
//Creating object using Builder pattern in java
Cake whiteCake = new Cake.Builder()
.sugar(1)
.butter(0.5)
.eggs(2)
.vanilla(2)
.flour(1.5)
.bakingPowder(0.75)
.milk(0.5)
.build();
//Cake is ready to eat :)
System.out.println(whiteCake);
}
}
Output:
Cake{sugar=0.75, butter=0.5, eggs=2, vanila=2, flour=1.5, bakingpowder=0.0, milk=0.5, cherry=0}
For full implementation and a very good explanation, please check
http://javarevisited.blogspot.mx/2012/06/builder-design-pattern-in-java-example.html

enum inheritance, or something similar

I have a string (which is a message) that I get as input and I need to do one of 4 possible things depending on the string
I know that there is eunm.valueOf() option, but I have 4 different enums, each with few possible messages.
looks something like:
public enum first{ONE,TWO,THREE};
public enum second{FOUR,FIVE,SIX};
public enum third{SEVEN,EIGHT,NINE};
public void work(String message){
//Here I want to compare message string to one of the 3 enums
}
is it possible to do this in one method of the enum?
or should I just try to create one, and if I get an exception try the other and so on?
As others have commented, it may be better to think through whether you really need 4 distinct enums.
But if you do, you could have them implement a common interface. Then you can map the input strings to the appropriate enum member, and call its method to accomplish what you want. Something like
public interface SomeInterface {
void doSomething();
};
public enum First implements SomeInterface {
ONE,TWO,THREE;
#Override
public void doSomething() { ... }
};
...
Map<String, SomeInterface> myMap = new HashMap<String, SomeInterface>();
for (First item : First.values()) {
myMap.put(item.toString(), item);
}
...
public void work(String message){
SomeInterface obj = myMap.get(message);
if (obj != null) {
obj.doSomething();
}
}
This assumes that the 4 possible things you want to do correspond to the 4 enums. If not, you can override the method separately for each and any enum member too, e.g.
public enum First implements SomeInterface {
ONE,
TWO {
#Override
public void doSomething() { // do something specific to TWO }
},
THREE;
#Override
public void doSomething() { // general solution for all values of First }
};
Enumerations in Java are full blown classes. Individual values can even override the behavior to meet their needs. It's pretty cool. You can use this to your advantage:
public enum Value implements Worker
{
ONE,
TWO,
THREE
{
#Override
public void doWork(String message)
{
// overrides behavior of base enum
}
},
FOUR,
/* ... */,
NINE;
private final String message;
Value() { this(""); }
Value(String message) { this.message = message; }
public void doWork(String message)
{
if (this.message.equals(message))
{
/* ... */
}
}
}
public interface Worker
{
void doWork(String message);
}
You can create a Map of them all
static final Map<String, Enum> enumMap = new LinkedHashMap<String, Enum>(){{
for(First e: First.values()) put(e.name(), e);
for(Second e: Second.values()) put(e.name(), e);
for(Third e: Third.values()) put(e.name(), e);
}};
Enum e = enumMap.get(name);
What you're really looking for is a aggregation of the other enums. The easiest way to get that is to make a new enum that puts all of those choices in a new enum. Something to this effect:
public enum Combination {
NEWONE(first.ONE), NEWTWO(first.TWO), NEWTHREE(first.THREE),
NEWFOUR(second.FOUR), NEWFIVE(second.FIVE), NEWSIX(second.SIX),
NEWSEVEN(third.SEVEN), NEWEIGHT(third.EIGHT), NEWNINE(third.NINE);
private String contents;
public Combination(first f) {
contents = f.toString();
}
public Combination(second s) {
contents = s.toString();
}
public Combination(third t) {
contents = t.toString();
}
public String toString() {
return contents;
}
}
This will more correctly aggregate the previous enums into a single data structure.
Even given your odd/even example in the comments, I don't feel multiple enums are the way to go here. I would use something like (warning, untested):
public enum Numbers {
ONE("first"), TWO("first"), THREE("first"), FOUR("second"), FIVE("second"), SIX("second"), SEVEN("third"), EIGHT("third"), NINE("third")
private String type;
Numbers(String t) { this.type = t; }
String getType { return this.type; }
}
Then you can use valueOf() to look up the enum element, and getType() to find out which of your three categories it belongs to.
It isn't entirely clear what you are asking, but perhaps you want to define a mapping between strings and constants, like this:
enum Type { FIRST, SECOND, THIRD };
Map<String, Type> mapping = new HashSet<String, Type>(){{
put("ONE", Type.FIRST);
put("TWO", Type.FIRST);
//...
put("NINE", Type.THIRD);
}};
public Type getTypeFromString(String s) {
return mapping.get(s);
}

Categories

Resources