How to convert an Optional to an OptionalInt? - java

I have an Optional that I want to "convert" to an OptionalInt, but there doesn't seem to be a simple way to do this.
Here's what I want to do (contrived example):
public OptionalInt getInt() {
return Optional.ofNullable(someString).filter(s -> s.matches("\\d+")).mapToInt(Integer::parseInt);
}
However, there's no mapToInt() method for Optional.
The best I could come up with is:
return Optional.ofNullable(someString)
.filter(s -> s.matches("\\d+"))
.map(s -> OptionalInt.of(Integer.parseInt(s)))
.orElse(OptionalInt.empty());
but that seems inelegant.
Am I missing something from the JDK that can make the conversion more elegant?

While the code isn't more readable than an ordinary conditional expression, there is a simple solution:
public OptionalInt getInt() {
return Stream.of(someString).filter(s -> s != null && s.matches("\\d+"))
.mapToInt(Integer::parseInt).findAny();
}
With Java 9, you could use
public OptionalInt getInt() {
return Stream.ofNullable(someString).filter(s -> s.matches("\\d+"))
.mapToInt(Integer::parseInt).findAny();
}
As said, neither is more readable than an ordinary conditional expression, but I think, it still looks better than using mapOrElseGet (and the first variant doesn't need Java 9.

No, there's no way to do it in more elegant way using standard Java API. I asked Paul Sandoz about adding mapToInt, etc., here's his answer:
Me:
Isn't it a good idea to provide also a way
to transfer between Optional types like mapToInt, mapToObj, etc.,
like it's done in Stream API?
Paul:
I don’t wanna go there, my response is transform Optional* into a *Stream. An argument for adding mapOrElseGet (notice that the primitive variants return U) is that other functionality can be composed from it.
So you will likely to have in Java-9:
return Optional.of(someString).filter(s -> s.matches("\\d+"))
.mapOrElseGet(s -> OptionalInt.of(Integer.parseInt(s)), OptionalInt::empty);
But nothing more.
That's because JDK authors insist that the Optional class and its primitive friends (especially primitive friends) should not be widely used, it's just a convenient way to perform a limited set of operations on the return value of methods which may return "the absence of the value". Also primitive optionals are designed for performance improvement, but actually it's much less significant than with streams, so using Optional<Integer> is also fine. With Valhalla project you will be able to use Optional<int> and OptionalInt will become unnecessary.
In your particular case the better way to do it is using ternary operator:
return someString != null && someString.matches("\\d+") ?
OptionalInt.of(Integer.parseInt(someString)) : OptionalInt.empty();
I assume that you want to return the OptionalInt from the method. Otherwise it's even more questionable why you would need it.

If you have any object and not just a String, you can temporarily go through a Stream:
public static <T> OptionalInt toOptionalInt(Optional<T> optional, ToIntFunction<? super T> func) {
return optional.map(Stream::of).orElseGet(Stream::empty)
.mapToInt(func)
.findFirst();
}
This solution has the advantage to be a one-liner, meaning you can copy/paste the content of the method and just change func to whatever you want. The disadvantage is going through a Stream to achieve what you want. But if you want a generic one-liner, this is it.
If you want a utility method, you probably prefer to use the following:
public static <T> OptionalInt toOptionalInt(Optional<T> optional, ToIntFunction<? super T> func) {
if (optional.isPresent()) {
return OptionalInt.of(func.applyAsInt(optional.get()));
} else {
return OptionalInt.empty();
}
}

This is how I convert an Optional<String> to OptionalInt
OptionalInt lastSeenId = Optional.of("123").map(Integer::parseInt).map(OptionalInt::of).orElseGet(OptionalInt::empty);

Here's another option that doesn't need to use a Stream and avoids compiling regex every time:
private static final Predicate<String> IS_DIGITS = Pattern.compile("^\\d+$")
.asPredicate();
public OptionalInt getInt() {
return Optional.ofNullable(someString)
.filter(IS_DIGITS)
.map(Integer::valueOf)
.map(OptionalInt::of)
.orElseGet(OptionalInt::empty);
}
Note that you need to anchor the regex because asPredicate() uses find() instead of matches().
Or if you're using Guava, you can eliminate the regex entirely and use their Ints class:
public OptionalInt getInt() {
return Optional.ofNullable(someString)
.map(Ints::tryParse)
.map(OptionalInt::of)
.orElseGet(OptionalInt::empty);
}

Related

Filter collection in Kotlin with existing java.util.Predicate instance

I want to filter a collection of values in Kotlin using an instance of a java.util.Predicate implementation, basically something like this:
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter(predicate)
This doesn't compile though. The following works, is that the recommended way of doing this? Feels a bit cumbersome
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter { predicate.test(it) }
You can use a method reference, which gets converted implicitly to a (T) -> Boolean and thus allows you to call the filter method:
schedule.sport_events.filter(predicate::test)
To answer it more directly: yes... predicate.test(it) or the nearly equivalent method reference predicate::test are the way to go... except...
If you have to deal with Java predicates more often and/or the refactoring of the Java functional types (e.g. Predicate) to Kotlin function types is planned in future, you may also want to add appropriate extension functions instead, e.g.:
fun <T> Iterable<T>.filter(predicate: Predicate<T>) = filter { predicate.test(it) }
With the following usage then:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
listOf("hello", "world")
.filter(javaPredicate)
If you replaced the Predicate in future to, e.g. (T) -> Boolean you then don't need to adapt that filter, but just replace/remove the import statement to the extension function.
Extension functions to just transform the Predicate to an appropriate Kotlin function type are possible too, but may not help you that much in future refactorings:
operator fun <T> Predicate<T>.invoke() : (T) -> Boolean = ::test
fun <T> Predicate<T>.transform() : (T) -> Boolean = ::test
Usage samples of those:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
// variant with Predicate.invoke:
listOf("hello", "world")
.filter(javaPredicate())
// variant using Predicate.transform()
listOf("hello", "world")
.filter(javaPredicate.transform())
So I recommend you the overloaded filter-method in case you plan a refactoring or otherwise just stick to filter { predicate.test(it) }/filter(predicate::test), which might make a future refactoring a bit (IDEs help ;-)) harder.

Math.toIntExact inside lambda expression?

I'm learning about lambda expressions.
Given a list of names, I want to count the numbers of names that start with N.
I did that:
final static List<String> friends = Arrays.asList("Brian", "Nate", "Neal", "Raju", "Sara", "Scott");
public static int countFriendsStartWithN() {
return Math.toIntExact(friends
.stream()
.filter(name -> name.startsWith("N"))
.count());
}
The call to the count method returns a primitive long but I want an int.
I used Math.toIntExact to get the long value as int.
Is it possible to get the int value directly inside the lambda expression?
No, it is not possible to fit your call to toIntExact into your chain of method calls, your stream pipeline. This is because count is a terminal operation and returns a primitive long on which no method call is possible. A terminal operation is an operation that ends the stream pipeline and produces a result (or a side effect).
So I believe the best thing you can do is to live with the code you already have. IMHO it’s fine.
Well, here's a somewhat silly way of calculating the count as an int without casting:
public static int countFriendsStartWithN() {
return friends.stream()
.filter(name -> name.startsWith("N"))
.mapToInt (s -> 1)
.sum();
}
You can't do anything inside the lambda expression you currently have, since that's a Predicate: it returns a boolean. Math.toIntExact returns an int.
You can do it without the Math.toIntExact (or a simple cast) like so:
return /* create stream, filter */
.mapToInt(a -> 1).sum();
But this is likely to be slower than doing what you are doing at the moment.
Yet another option that is not really better - it is possible to use a collector that applies a finisher:
public static int countFriendsStartWithN() {
return friends.stream()
.filter(name -> name.startsWith("N"))
.collect(Collectors.collectingAndThen(Collectors.counting(), Math::toIntExact));
}
This may have an advantage if you need it frequenty - you could build a utility method returning this Collector to make it reusable.
Here's a way to do this with reduce
public static int countFriendsStartWithN2() {
return friends
.stream()
.filter(name -> name.startsWith("N"))
.map(s -> 1)
.reduce(0, Integer::sum);
}

Good way to convert Optional<Integer> to Optional<Long>

I am trying to find a clean and code-efficient way to convert Optional<Integer> to Optional<Long>. I am working in Java 7 with Guava.
So in one place in the code I have an optional integer created
Optional<Integer> optionalInt = Optional.fromNullable(someInt);
And in another area I need it as an optional long.
The nicest thing I could come up with is this:
Optional<Long> optionalLong = optionalInt.transform(new Function<Integer, Long>() {
#Override
public Long apply(Integer inputInt) {
if (inputInt != null)
return inputInt.longValue();
else
return null;
}
});
But this is cumbersome, especially if you consider how easy it was to cast the type when I was using primitive types.
Any good ideas out there?
TL;DR: In Java 7, No.
Sadly this is the best Java 7 has to offer in terms of support for functions.
I would just say that transform will never be called with null so you can do:
Optional<Long> optionalLong = optionalInt.transform(new Function<Integer, Long>() {
#Override
public Long apply(Integer inputInt) {
return inputInt.longValue();
}
});
From the documentation:
If the instance is present, it is transformed with the given
Function; otherwise, absent() is returned. If the function returns
null, a NullPointerException is thrown.
So never return null from a Function passed to transform.
If you reuse this a lot, then you could use the enum singleton pattern:
public enum IntToLong implements Function<Integer, Long> {
INSTANCE;
#Override
public Long apply(Integer input) {
return input.longValue();
}
}
Then:
optionalInt.transform(IntToLong.INSTANCE);
This obviously reduces the code at the call site at the expense of having extra classes in the code base - something I wouldn't be too worried about.
close to the cast:
Optional<Long> optionalLong = Optional.fromNullable(optionalInt.isPresent() ?
optionalInt.get().longValue() : null);
basically this avoids the overhead of invoking transform. Invoking isPresent could be simplified to checking the value for null directly.

Convert Stream to IntStream

I have a feeling I'm missing something here. I found myself doing the following
private static int getHighestValue(Map<Character, Integer> countMap) {
return countMap.values().stream().mapToInt(Integer::intValue).max().getAsInt();
}
My problem is with the silly conversion from Stream to IntStream via the mapToInt(Integer::intValue)
Is there a better way of doing the conversion? all this is to avoid using max() from Stream, which requires passing a Comparator but the question is specifically on the convertion of Stream to IntStream
Due to type erasure, the Stream implementation has no knowledge about the type of its elements and can’t provide you with neither, a simplified max operation nor a conversion to IntStream method.
In both cases it requires a function, a Comparator or a ToIntFunction, respectively, to perform the operation using the unknown reference type of the Stream’s elements.
The simplest form for the operation you want to perform is
return countMap.values().stream().max(Comparator.naturalOrder()).get();
given the fact that the natural order comparator is implemented as a singleton. So it’s the only comparator which offers the chance of being recognized by the Stream implementation if there is any optimization regarding Comparable elements. If there’s no such optimization, it will still be the variant with the lowest memory footprint due to its singleton nature.
If you insist on doing a conversion of the Stream to an IntStream there is no way around providing a ToIntFunction and there is no predefined singleton for a Number::intValue kind of function, so using Integer::intValue is already the best choice. You could write i->i instead, which is shorter but just hiding the unboxing operation then.
I realize you are trying to avoid a comparator, but you could use the built-in for this by referring to Integer.compareTo:
private static int getHighestValue(Map<Character, Integer> countMap) {
return countMap.values().stream().max(Integer::compareTo).get();
}
Or as #fge suggests, using ::compare:
private static int getHighestValue(Map<Character, Integer> countMap) {
return countMap.values().stream().max(Integer::compare).get();
}
Another way you could do the conversion is with a lambda: mapToInt(i -> i).
Whether you should use a lambda or a method reference is discussed in detail here, but the summary is that you should use whichever you find more readable.
If the question is "Can I avoid passing converter while converting from Stream<T> to IntStream?" one possible answer might be "There is no way in Java to make such conversion type-safe and make it part of the Stream interface at the same time".
Indeed method which converts Stream<T> to IntStream without a converter might be looked like this:
public interface Stream<T> {
// other methods
default IntStream mapToInt() {
Stream<Integer> intStream = (Stream<Integer>)this;
return intStream.mapToInt(Integer::intValue);
}
}
So it suppose to be called on Stream<Integer> and will fail on other types of streams. But because streams are lazy evaluated and because of the type erasure (remember that Stream<T> is generic) code will fail at the place where stream is consumed which might be far from the mapToInt() call. And it will fail in a way that is extremely difficult to locate source of the problem.
Suppose you have code:
public class IntStreamTest {
public static void main(String[] args) {
IntStream intStream = produceIntStream();
consumeIntStream(intStream);
}
private static IntStream produceIntStream() {
Stream<String> stream = Arrays.asList("1", "2", "3").stream();
return mapToInt(stream);
}
public static <T> IntStream mapToInt(Stream<T> stream) {
Stream<Integer> intStream = (Stream<Integer>)stream;
return intStream.mapToInt(Integer::intValue);
}
private static void consumeIntStream(IntStream intStream) {
intStream.filter(i -> i >= 2)
.forEach(System.out::println);
}
}
It will fail on consumeIntStream() call with:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at java.util.stream.ReferencePipeline$4$1.accept(ReferencePipeline.java:210)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateSequential(ForEachOps.java:189)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.IntPipeline.forEach(IntPipeline.java:404)
at streams.IntStreamTest.consumeIntStream(IntStreamTest.java:25)
at streams.IntStreamTest.main(IntStreamTest.java:10)
Having this stacktrace do you able to quickly identify that the problem is in produceIntStream() because mapToInt() was called on the stream of the wrong type?
Of course one can write converting method which is type safe because it accepts concrete Stream<Integer>:
public static IntStream mapToInt(Stream<Integer> stream) {
return stream.mapToInt(Integer::intValue);
}
// usage
IntStream intStream = mapToInt(Arrays.asList(1, 2, 3).stream())
but it's not very convenient because it breaks fluent interface nature of the streams.
BTW:
Kotlin's extension functions allow to call some code as it is a part of the class' interface. So you are able to call this type-safe method as a Stream<java.lang.Integer>'s method:
// "adds" mapToInt() to Stream<java.lang.Integer>
fun Stream<java.lang.Integer>.mapToInt(): IntStream {
return this.mapToInt { it.toInt() }
}
#Test
fun test() {
Arrays.asList<java.lang.Integer>(java.lang.Integer(1), java.lang.Integer(2))
.stream()
.mapToInt()
.forEach { println(it) }
}

Guava Optional type, when transformation returns another Optional

I have a method that procudes an Optional<String>
But this String must be parsed at another application level as Integer or Long.
This I have a Function<String, Integer> that can be applied on the String, to produce an Integer.
This transformation can fail because the String may not be an Integer parsable value.
I would like to return Optional when the transformation fails, instead of throwing a parsing exception.
I can't make the STRING_TO_INTEGER_FUNCTION return null, because it is not allowed by Guava:
Exception in thread "main" java.lang.NullPointerException: Transformation function cannot return null.
Thus the only thing I can do is having a Function<String,Optional<Integer>> but then I get as final result an Optional<Optional<Integer>> which isn't really cool because I may have another transformations to apply on it.
Does someone know how can I do something like that in Guava?
Optional.of("Toto").transform(STRING_TO_INTEGER_FUNCTION) = // Optional<Integer> ?
Thanks
I guess you can do:
public static void main(final String[] args) {
final Optional<Integer> valid = Optional.of("42")
.transform(STR_TO_INT_FUNCTION)
.or(Optional.<Integer>absent());
System.out.println(valid); // Optional.of(42)
final Optional<Integer> invalid = Optional.of("Toto")
.transform(STR_TO_INT_FUNCTION)
.or(Optional.<Integer>absent());
System.out.println(invalid); // Optional.absent()
final Optional<Integer> absent = Optional.<String>absent()
.transform(STR_TO_INT_FUNCTION)
.or(Optional.<Integer>absent());
System.out.println(absent); // Optional.absent()
}
private static final Function<String, Optional<Integer>> STR_TO_INT_FUNCTION =
new Function<String, Optional<Integer>>() {
#Override
public Optional<Integer> apply(final String input) {
return Optional.fromNullable(Ints.tryParse(input));
}
};
Usage isn't that clumsy when you use Optional -> transform -> or in one line (assigning transformed optional integer would produce Optional<Optional<Integer>>).
Using Optional.transform just doesn't seem compatible with a transformation that might fail - theoretically this implies an optional optional, when what you want to do is consolidate absences. I would recommend using something like the following:
Optional<String> strOptional = Optional.of("Toto");
Optional<Integer> intOptional =
strOptional.isPresent()
? Optional.fromNullable(Ints.tryParse(strOptional.get()))
: Optional.<Integer>absent();
Another options except those stated above:
use plain old if/else (Guava team recommends not to overuse such constructs, it's often wise to obey these recommendation - otherwise you won't spare much lines of code and make readability worse)
use dirty trick: from(singleton("Toto")).transform(STRING_TO_INTEGER_FUNCTION).filter(notNull()).first().orNull() - only hypothetical idea, IMHO its badly readable too. At least it contains none generics, ?: operator or anonymous class, at the cost of more static imports.
wait for Java 8, where Optional.map allows null transformation result
You can vote for http://code.google.com/p/guava-libraries/issues/detail?id=1171 . Unfortunately Guava team seems hesitant with shifting this issue to some result.

Categories