I have been asked to 'translate' some Scala code to Java for a course. However, the requirements of the assignment are that Java 8 and external libraries, such as Functional Java and Totally Lazy, are not allowed. The line in Scala is:
charges.groupBy(_.cc).values.map(_.reduce(_ combine _)).toList
I have been able to write groupBy and values but .map and _.reduce still elude me. I have looked at the source code of those two libraries as well as the Scala source to try and find something to help me with putting these together but I have not been able to make any headway.
GroupBy is implemented as follows:
public Map<CreditCard, List<Charge>> groupBy(List<Charge> list)
{
Map<CreditCard, List<Charge>> map = new TreeMap<CreditCard, List<Charge>>();
for(Charge c: list)
{
List<Charge> group = map.get(c.cc);
if(group == null)
{
group = new ArrayList();
map.put(c.cc, group);
}
group.add(c);
}
return map;
}
you can use Google Guava for this. it doesn't require java8. you would especially be interested in class which call FluentIterable. here's some methods that could help you:
index(Function keyFunction) - the function used to produce the key for each value
transform(Function function) - applies {#code function} to each element of this fluent iterable
and there are a lot more.
You'll have to iterate over the values. Ordinarily I'd suggest using a new style for loop. Something like:
for (ValuesType value : values) {
// do your map and reduce here
}
The problem with that is you need to have access to more than one value at a time. (See discussion of .reduce(), below.) So perhaps the old style for would be better:
for (int i = 0; i < values.length - 1; i++) {
// do something with values.get(i) or values[i] as needed
}
Point to ponder: why values.length - 1?
.map() simply transforms one thing into another. What's the transformation in this case? It's the .reduce()! So that should be easy enough.
The _ in _.reduce() is the equivalent of value in the for statement above. It's the one value that you're dealing with on this iteration.
.reduce() takes two values and does something to them to turn them into a single value. To make that work you'll need to deal with values.get(i) and values.get(i+1) somehow. And _ combine _, well, you tell me.
Related
I have the following code
//assume we have a list of custom type "details" already constructed
for(int i = 0; i < details.size(); ++i) {
CallerID number = details.get(i).getNextNumber();
ClientData.addToClient(number);
}
I have oversimplified the code. The enum CallerID and the ClientData object work as intended. I am asking for help converting this loop to a lambda function so I can understand the logic of how to do so, then fill in the appropriate code as needed.
Let's first write it as a modern basic for loop and golf it a bit, just so we're comparing apples to apples:
for (var detail : details) clientData.addToClient(detail.getNextNumber());
And this is probably the right answer. It is local var, exception, and control flow transparent (which is what you want), and short.
The lambda form is this, but it's got downsides (mostly, those transparencies). It also isn't any shorter. You shouldn't write it this way.
details.stream().forEach(d -> clientData.addToClient(detail.getNextNumber());
You may be able to just remove stream() from that. But probably not.
Generally when people say "I want it in lambda form", that's not because someone is holding a gun to your head - you are saying that because somebody peddling a religion of sorts to you told you that 'it was better' and that this 'will scale'. Realize that they are full of it. There can be advantages to 'functional style', but none of these snippets are functional. A true functional style would involve a bunch of side-effect-free transformations, and then returning something.
.addToClient? You've lost the functional game there - you would want to instead convert each detail to something (presumably a ClientID), and from there construct an immutable object from that stream. You'd 'collect' your ClientIDs into a clientData object.
Let's say for example that clientData is just a 'list of ClientIDs' and nothing more. Then you'd write something like this:
var clientData = details.stream()
.map(MyDetailClass::getNextNumber)
.collect(Collectors.toList());
Is this better? No. However, if you're looking for 'a stream-style, lambda-based functional take on things', that qualifies. The output is constructed by way of collection (and not forEach that does a side-effect operation), and all elements involved are (or can be) immutable.
There's no particular reason why you'd want this, but if for some reason you're convinced this is better, now you know what you want to do. "Just replace it with a lambda" doesn't make it 'functional'.
I am asking for help converting this loop to a lambda function so I can understand the logic of how to do so, then fill in the appropriate code as needed.
A Function returns a value. As you are just updating something what you need is a Consumer which accepts a single argument of a list of some detail. Assuming those are in a Class named SomeDetails, here is how you would do it.
As you iterating over some structure limited by size and using get(i) I am presuming a list is required here.
List<SomeDetails> details = new ArrayList<>(); // then populated
// lambda definition
Consumer<List<SomeDetails>> update = (lst)-> {
for(SomeDetails detail : lst) {
CallerID number = detail.getNextNumber();
ClientData.addToClient(number);
}
};
And then invoke it like this, passing the List.
update.accept(details);
All the above does is encapsulate the for loop (using the enhanced version for simplicity) and perform the operation.
If this is all you wanted, I would recommend just doing it as you were doing it sans the lambda.
Like just about everyone, I'm still learning the intricacies (and loving them) of the new Java 8 Streams API. I have a question concerning usage of streams. I'll provide a simplified example.
Java Streams allows us to take a Collection, and use the stream() method on it to receive a stream of all of its elements. Within it, there are a number of useful methods, such as filter(), map(), and forEach(), which allow us to use lambda operations on the contents.
I have code that looks something like this (simplified):
set.stream().filter(item -> item.qualify())
.map(item -> (Qualifier)item).forEach(item -> item.operate());
set.removeIf(item -> item.qualify());
The idea is to get a mapping of all items in the set, which match a certain qualifier, and then operate through them. After the operation, they serve no further purpose, and should be removed from the original set. The code works well, but I can't shake the feeling that there's an operation in Stream that could do this for me, in a single line.
If it's in the Javadocs, I may be overlooking it.
Does anyone more familiar with the API see something like that?
You can do it like this:
set.removeIf(item -> {
if (!item.qualify())
return false;
item.operate();
return true;
});
If item.operate() always returns true you can do it very succinctly.
set.removeIf(item -> item.qualify() && item.operate());
However, I don't like these approaches as it is not immediately clear what is going on. Personally, I would continue to use a for loop and an Iterator for this.
for (Iterator<Item> i = set.iterator(); i.hasNext();) {
Item item = i.next();
if (item.qualify()) {
item.operate();
i.remove();
}
}
In one line no, but maybe you could make use of the partitioningBy collector:
Map<Boolean, Set<Item>> map =
set.stream()
.collect(partitioningBy(Item::qualify, toSet()));
map.get(true).forEach(i -> ((Qualifier)i).operate());
set = map.get(false);
It might be more efficient as it avoids iterating the set two times, one for filtering the stream and then one for removing corresponding elements.
Otherwise I think your approach is relatively fine.
There are many approaches. If you use myList.remove(element) you must override equals(). What I prefer is:
allList.removeIf(item -> item.getId().equals(elementToDelete.getId()));
Good luck and happy coding :)
After the operation, they serve no further purpose, and should be removed from the original set. The code works well, but I can't shake the feeling that there's an operation in Stream that could do this for me, in a single line.
You cannot remove elements from the source of the stream with the stream. From the Javadoc:
Most stream operations accept parameters that describe user-specified behavior..... To preserve correct behavior, these behavioral parameters:
must be non-interfering (they do not modify the stream source); and
in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).
What you really want to do is to partition your set. Unfortunately in Java 8 partitioning is only possible via the terminal "collect" method. You end up with something like this:
// test data set
Set<Integer> set = ImmutableSet.of(1, 2, 3, 4, 5);
// predicate separating even and odd numbers
Predicate<Integer> evenNumber = n -> n % 2 == 0;
// initial set partitioned by the predicate
Map<Boolean, List<Integer>> partitioned = set.stream().collect(Collectors.partitioningBy(evenNumber));
// print even numbers
partitioned.get(true).forEach(System.out::println);
// do something else with the rest of the set (odd numbers)
doSomethingElse(partitioned.get(false))
Updated:
Scala version of the code above
val set = Set(1, 2, 3, 4, 5)
val partitioned = set.partition(_ % 2 == 0)
partitioned._1.foreach(println)
doSomethingElse(partitioned._2)`
Nope, your implementation is probably the simplest one. You might do something deeply evil by modifying state in the removeIf predicate, but please don't. On the other hand, it might be reasonable to actually switch to an iterator-based imperative implementation, which might actually be more appropriate and efficient for this use case.
if I understand your question correctly:
set = set.stream().filter(item -> {
if (item.qualify()) {
((Qualifier) item).operate();
return false;
}
return true;
}).collect(Collectors.toSet());
I see Paul's clarity concern when using streams, stated in the top answer. Perhaps adding explaining variable clarifies intentions a little bit.
set.removeIf(item -> {
boolean removeItem=item.qualify();
if (removeItem){
item.operate();
}
return removeItem;
});
I'm using the for-each construct in Java as follows:
public int getNumRStations() {
int numRoutes = 0;
for (ArrayList<Route> route : routes) {
numRoutes += route.size();
}
return numRoutes;
}
NetBeans shows a warning/notice that says "Can use functional operations". Upon automatically resolving it, the newly generated code shows this:
public int getNumRStations() {
int numRoutes = 0;
numRoutes = routes.stream().map((route) -> route.size()).reduce(numRoutes, Integer::sum);
return numRoutes;
}
Why is NetBeans warning me of this? I know I'm not supposed to blindly trust IDEs, so that's why I'm asking.
What is that new line supposed to do? I haven't seen anything like it, in real life or in class.
That looks like NetBeans suggesting refactoring your sum operation as a Java 8 "lambda" or functional programming operation using the map and reduce functions from the Stream interface. You must be using a Java 8 JDK with NetBeans.
Breaking down what it's doing:
the "map()" function is performing a count of all of your route sizes in your routes array list,
the "reduce()" function is then performing a sum of those individual sizes to get the final result for the total number of routes.
The map() and reduce() functions are documented in the Java 8 documentation for the Stream interface available at this link
This answer addresses "what it is" but doesn't address "why it's better". I will admit to still learning about these constructs myself.
So #paisanco already explained about what each function does.
I agree that the modification the IDE suggested is more complex than the original.
If I were asked to select between the original one and the IDE's recommendation, then I will choose the original one.
However, here is a simpler (and more preferred) way for your example.
public int getNumRStations() {
return routes.stream().mapToInt(x -> x.size()).sum();
}
Explanation is simpler in this case, too.
For each routes' element x, change it into x.size() and sum them up.
x -> x.size() is called a lambda expression, or anonymous function.
It's like
int function(x) {
return x.size();
}
(I omitted the parameter type. The type is implicitly selected by the Java compiler.)
This function is applied to each of the collection's element. This is what mapToInt(lambda exp) method does.
sum() method doesn't seem to need explanation.
Simple, isn't it?
I am trying to implement this but I can't find a good paper or description of how to do it, could you guys point me in the right direction please? I do have an implementation of it in C# but I don't know enough to just convert the code to Java.
As per a comment I'm adding some of the C# Code I haven't been able to convert to Java:
//T with the smallest func(t)
static T MinBy<T, TComparable>(this IEnumerable<T> xs, Func<T, TComparable> func) where TComparable : IComparable<TComparable>{
return xs.DefaultIfEmpty().Aggregate((maxSoFar, elem) => func(elem).CompareTo(func(maxSoFar)) > 0 ? maxSoFar : elem);
}
//returns an ordered set of nearest neighbors
static IEnumerable<Stop> NearestNeighbors(this IEnumerable<Stop> stops){
var stopsLeft = stops.ToList();
for (var stop = stopsLeft.First(); stop != null; stop = stopsLeft.MinBy(s => Stop.Distance(stop, s))){
stopsLeft.Remove(stop);
yield return stop;
}
}
I assume you are not familiar with C#. So I will try to explain some of the things in short.
IEnumerable<T> is C#'s equivalent of java's Iterable<T>
Func<T, V> is an abstraction of a method who's input is T and return value is V. C#, unlike Java, supports closures, but they are effectively like java anonymous classes, without all the syntactic fuss around. So basically, the second argument of MinBy is a means to extract the property from T is relevant for comparison. You could easily implement the very same abstraction with an anonymous class, but it will not be as concise.
The strange this modifier that comes before the first argument is saying that this is an extension method. It solely serves a syntactic sugar purpose. When a method is define like this, it means that it can be called on the instance of the first argument (that has the this modifier before it). This allowes you to write code like:
IEnumerable<String> seq = getS();
seq.MinBy(/*bla*/);
instead of explicitly specifying the Utility class the static method is defined in:
MyUtility.MinBy(s, /*bla*/);
You probably do not need this high level of abstraction (and lets face it, java is simply not built for it today) so what you want to do is to define a method instead of MinBy that inputs an Iterable leftStops and another Stop currentStop and finds the closest stop to currentStop from leftStops.
Something like:
Stop findClosest(Stop currentStop, Iterable<Stop> left stops) {/*implement me*/}
That done, lets turn to NearestNeighbors itself. What is that yield return? it is a very powerful way to implelent iterators in .Net. I feel that a full explanation on its workings is beyond the scope of our discussion, so I have rewritten the method not to use this feature in a way that conserves its functionality (and removed the this qualifier of its first argument):
static IEnumerable<Stop> NearestNeighbors(IEnumerable<Stop> stops){
IEnumerable<Stop> result = new List<stop>();
var stopsLeft = stops.ToList();
for (var stop = stopsLeft.First(); stop != null; stop = stopsLeft.MinBy(s => Stop.Distance(stop, s))){
stopsLeft.Remove(stop);
result.Add(stop);
}
return result;
}
So we are left with the following algorithm:
Input a list of Stops
next-stop = first-stop
Remove next-stop from the Stop list
Find the closest stop to next-stop and set next-stop=closest
if there are more stops, go to 3
Return the stops in the order they were visited.
Hopefully it is clearer now.
I read an article on Joel On Software about the idea of using higher order functions to greatly simplify code through the use of map and reduce. He mentioned that this was difficult to do in Java. The article: http://www.joelonsoftware.com/items/2006/08/01.html
The example from the article below, loops through an array, and uses the function fn that was passed as an argument on each element in the array:
function map(fn, a)
{
for (i = 0; i < a.length; i++)
{
a[i] = fn(a[i]);
}
}
This would be invoked similar to the below in practice:
map( function(x){return x*2;}, a );
map( alert, a );
Ideally I'd like to write a map function to work on arrays, or Collections of any type if possible.
I have been looking around on the Internet, and I am having a difficult time finding resources on the subject. Firstly, are anonymous functions possible in java? Is this possible to do in another way? Will it be available in a future version of java? If possible, how can I do it?
I imagine that if this is not possible in Java there is some kind of 'pattern'/technique that people use to achieve the same effect, as I imagine anonymous functions are a very powerful tool in the software world. the only similar question I was able to find was this: Java generics - implementing higher order functions like map and it makes absolutely no sense to me.
Guava provides map (but it's called transform instead, and is in utility classes like Lists and Collections2). It doesn't provide fold/reduce, however.
In any case, the syntax for using transform feels really clunky compared to using map in Scheme. It's a bit like trying to write with your left hand, if you're right-handed. But, this is Java; what do you expect. :-P
Looks like this one?
How can I write an anonymous function in Java?
P.S: try Functional Java. Maybe it could give you hints.
Single method anonymous classes provide a similar, but much more verbose, way of writing an anonymous function in Java.
For example, you could have:
Iterable<Source> foos = ...;
Iterable<Destination> mappedFoos = foos.map(new Function<Source, Destination>()
{
public Destination apply(Source item) { return ... }
});
For an example of a Java library with a functional style, see Guava
interface Func<V,A> {
V call (A a);
}
static <V,A> List<V> map (Func<V,A> func, List<A> as) {
List<V> vs = new ArrayList<V>(as.size());
for (A a : as) {
Vs.add(func.call(a));
}
return vs;
}
Paguro has an open-source implementation of higher order functions. Initial test show it to be 98% as fast as the native Java forEach loop. The operations it supports are applied lazily without modifying the underlying collection. It outputs to type-safe versions of the immutable (and sometimes mutable) Clojure collections. Transformable is built into Paguro's unmodifiable and immutable collections and interfaces. To use a raw java.util collection as input, just wrap it with the xform() function.