Is it possible to pass an argument to a lambdaj Predicate?
public static Matcher<SomeObject> isSpecialObject = new Predicate<SomeObject>() {
public boolean apply(SomeObject specialObj) {
return LIST_OF_SPECIAL_IDS.contains(specialObj.getTypeId());
}
};
I would like to alter the above predicate so I can pass in a list, rather than use the static list LIST_OF_SPECIAL_IDS. Is that possible?
Thanks.
I suspect you want something like:
public static Matcher<SomeObject> createPredicate(final List<String> ids) {
return new Predicate<SomeObject>() {
public boolean apply(SomeObject specialObj) {
return ids.contains(specialObj.getTypeId());
}
};
}
You've got to make it a method rather than just a field, as otherwise you've got nowhere to pass the list. The parameter has to be final so that you can use it within the anonymous inner class.
Related
I have a function like this:
public static String getNumberOfItemsInList(Order[] orders) {
return String.valueOf(objects.length);
}
I must use this function in many options:
getNumberOfItemsInList(list of ordres);
getNumberOfItemsInList(list of users);
getNumberOfItemsInList(list of services);
How to pass in the parameter of the function List that would take any type we give it? I don't want to create a function for any type of the list,
can somebody help me?
Write 2 methods, so you're covered regarding the definition of "list":
public static String getNumberOfItemsInList(Object[] array) {
return String.valueOf(array.length);
}
public static String getNumberOfItemsInList(Collection<?> coll) {
return String.valueOf(coll.size());
}
The first can handle all types of arrays, and the second can handle all types of collections, including all types of lists.
try this
public static <T> String getLength(T[] items) {
return String.valueOf(items.length);
}
Say I have 2 methods that look like this:
private static boolean validate1(String line)
private static boolean validate2(String line)
The method I use depends what the user passes in as an argument so I only ever want to use one of the methods.
If I wanted to loop through a list of strings would I have to check each time what method to use or is there a way I could store the method I wanted and just call it with the parameters like a function pointer?
Because the signature of your validate methods are the same, you can map a Function<String, Boolean> to a string like so:
class Main {
public static boolean validate1(String s) { return true; }
public static boolean validate2(String s) { return false; }
public static void main(String[] args) {
Map<String, Function<String, Boolean>> funcMap = new HashMap<>();
funcMap.put("First", Main::validate1);
funcMap.put("Second", Main::validate2);
System.out.println(funcMap.get("First").apply("Wow!"));
}
}
The output here would be true.
If you use Java 8 or higher, you can do the following.
Create a functional interface for your methods like this:
#FunctionalInterface
interface Validator {
boolean validate(String s);
}
In you class with your 2 static methods, you can now assign one of these methods to a variable. Depending on the argument, you can assign the validate1 method:
Validator v = this::validate1;
or the validate2 method:
Validator v = this::validate2;
Then you can use your Validator object in your loop to perform your validation.
for(String s : strings) {
v.validate(s);
}
Or with the new forEach() method in the List interface, or with the Streams API. You can use it how you like.
is there any way I can declare constructor to take HashSet as one of arguments and then pass HashSet value directly as argument during object initialization?
I mean something like this:
public class Order {
private Set<Product> products = new HashSet<Product>();
public Order (???) {
this.products = ???
}
}
and then, while initializing object:
Order order = new Order("product1", "product2", "product3");
is it possible?
You can use varargs :
public class Order {
private Set<Product> products;
public Order (Product... products) {
this.products = new HashSet<Product> (Arrays.asList(products));
}
}
But then you pass to the constructor Product instances :
Order order = new Order(new Product("product1"), new Product("product2"), new Product("product3"));
I would recommend something like:
public class Order {
private final Set<String> strings;
public Order(final Set<String> strings) {
this.strings = strings;
}
public Order(final String... strings) {
this(toSet(strings));
}
private static Set<String> toSet(String[] strings) {
final Set<String> ss = new HashSet<>();
for (final String s : strings) {
if (!ss.add(s)) {
throw new IllegalArgumentException("Duplicate string " + s);
}
}
return ss;
}
}
This takes a varargs argument, which allows you to invoke the constructor as you would like.
It also checks for duplicates during initialization, I would suggest that duplicates are an error; but you could just log it and carry on.
The above looks to me like you want a constructor taking varargs of String type, and then create the HashSet via those varargs.
A HashSet can't be created via varargs, so perhaps create the set and then add each element in turn. Or create a collection of those vararg elements, and then construct the HashSet directly from that.
If you really need to use the HashSet in the constructor, I would do something like this in the constructor:
public Order (HashSet<String> myHashSet)
Then, whenever you want to initialise it, call it this way:
Order order = new Order(new HashSet<String>(Arrays.asList("product1", "product2")));
It's not very time efficient, but it works.
I'm new in java. I need check if enum element is into enum set.
in Delphi:
type
TWeekEnum = (weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday)
TWeekSetEnum = (weSaturday, weSunday)
if (weSunday in (TWeekSetEnum))
...
Java?
You can define the enum this way, and then also create your subsets as static methods on it.
public enum TWeekEnum {
weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday;
public static EnumSet<TWeekEnum> getWeekend() {
return EnumSet.of(weSaturday, weSunday);
}
public static EnumSet<TWeekEnum> getWeekDays() {
return EnumSet.complementOf(getWeekend());
}
}
Then you can check if it contains your selected item like this
TWeekEnum.getWeekend().contains(TWeekEnum.weTuesday)
If you prefer the elements to be in the calling code (and not inside the enum) - another solution is to add a normal method named in as follows: -
public enum TWeekEnum {
weMonday, weTuesday, weWednesday, weThursday, weFriday, weSaturday, weSunday;
public boolean in (TWeekEnum ... weekEnum) {
return Arrays.asList(types).contains(this);
}
}
This can be called anywhere in the codebase as follows: -
TWeekEnum weekEnum = TWeekEnum.weSaturday; // <---- If set dynamically, check for null
if (weekEnum.in(TWeekEnum.weSaturday, TWeekEnum.weSunday)) {
// do something
}
... this can look nicer (and read better) if enum values statically imported i.e.
import static com.foo.TWeekEnum.weSaturday;
import static com.foo.TWeekEnum.weSunday;
...
if (weekEnum.in(weSaturday, weSunday)) {
// do something
}
If my method call is:
obj.getLevelOne().getLevelTwo().getValue();
And I want to pass this method as a parameter below:
boolean checkValue( obj, method , value)
{
return obj.method() == value;
}
I want to call the checkValue method like this:
checkValue(obj, "getLevelOne().getLevelTwo().getValue", value);
Is there any way I can accomplish this? Please help.
In java Functions are not a first class concept (yet, coming in Java 8). So it's not possible to pass a method as you can in many other languages that have functional concepts.
What you need to do instead is declare an interface and implement it using an anonymous inner class. e.g.
The Interface
interface MyGetter {
Object doGet();
}
The Check Method
boolean checkValue(MyGetter getter, Object value) {
return getter.doGet().equals(value);
}
The Call
checkValue(new MyGetter() {
public Object doGet() {
return obj.getLevelOne().getLevelTwo().getValue();
}
}, 5);
What we're actually doing in the call is creating a new class and an object of that type to make the actual call you need.
Edit:
If you need different return types you can make the interface and check method generic, e.g.
The Interface
interface MyGetter<T> {
T doGet();
}
The Check Method
<T> boolean checkValue(MyGetter<? extends T> getter, T value) {
return getter.doGet().equals(value);
}
The Call
checkValue(new MyGetter<SomeClass>() {
public SomeClass doGet() {
return obj.getLevelOne().getLevelTwo().getValue();
}
}, 5);
If you really want to do something like this, i recommend either:
1.use a Callable and create anonymous subclasses. NOTE: this is somewhat similar to the approach given above with "MyGetter", except that it uses Callable. There's no need for our own interface, since we can use something that was intended for this purpose that's built into the jdk.
public <T> boolean checkValue(Callable<T> valueGetter, T value) {
return value.equals(valueGetter.call());
}
final MyObject obj = new MyObject();
checkValue(new Callable<String>() {
public String call() { return obj.getLevelOne().getLevelTwo().getValue(); }
}, "foo");
2.using some sort of EL package (mvel works well as an embedded library).
You could then do: "levelOne.levelTwo.value" as your expression, and use mvel to evaluated in on "obj".
public <T> boolean checkValue(Object obj, String expression, T value) {
Object objVal = MVEL.eval(expression, obj);
return value.equals(objVal);
}
checkValue(obj, "levelOne.levelTwo.value", "foo");
Of course, the first one is much more typesafe, though your "expression" would be done at compile time since you're explicitly coding it into the callable implemention. The second approach is more dynamic and lets you compute the expression at runtime.