What is the difference between "Iterables" and "Iterators"? - guava

I'm a newbie with google guava. I don't know when we should use "Iterables" or "Iterators". Could you help me explain them?

See the wiki:
As a result, many of the operations you might expect to see supported
for all collections can be found in Iterables. Additionally, most
Iterables methods have a corresponding version in Iterators that
accepts the raw iterator.
Many methods in Iterables call the coresponsding methods in Iterators.
p-code:
Iterables.operation(Iterables it){
if(it is-a Collection)
return it.operation();
else
return Iterators.operation(it.iterator());
}

Related

How to find max date from stream in scala using CompareTo?

I am new to Scala and trying to explore how I can use Java functionalities with Scala.
I am having stream of LocalDate which is a Java class and I am trying to find maximum date out of my list.
var processedResult : Stream[LocalDate] =List(javaList)
.toStream
.map { s => {
//some processing
LocalDate.parse(str, formatter)
}
}
I know we can do easily by using .compare() and .compareTo() in Java but I am not sure how do I use the same thing over here.
Also, I have no idea how Ordering works in Scala when it comes to sorting.
Can anyone suggest how can get this done?
First of all, a lot of minor details that I will point out since it seems you are pretty new to the language and I expect those to help you with your learning path.
First, avoid var at all costs, especially when learning.
While mutability has its place and is not always wrong, forcing you to avoid it while learning will help you. Particularly, avoid it when it doesn't provide any value; like in this case.
Second, this List(javaList) doesn't do what you think it does. It creates a single element Scala List whose unique element is a Java List. What you probably want is to transform that Java List into a Scala one, for that you can use the CollectionConverters.
import scala.jdk.CollectionConverters._ // This works if you are in 2.13
// if you are in 2.12 or lower use: import scala.collection.JavaConverters._
val scalaList = javaList.asScala.toList
Third, not sure why you want to use a Scala Stream, a Stream is for infinite or very large collections where you want all the transformations to be made lazily and only produce elements as they are consumed (also, btw, it was deprecated in 2.13 in favour of LazyList).
Maybe, you are confused because in Java you need a "Stream" to apply functional operations like map? If so, note that in Scala all collections provide the same rich API.
Fourth, Ordering is a Typeclass which is a functional pattern for Polymorphism. On its own, this is a very broad question so I won't answer it here, but I hope the two links provide insight.
The TL;DR; is simple, it is just that an Ordering for a type T knows how to order (sort) elements of type T. Thus operations like max will work for any collection of any type if, and only if, the compiler can prove the existence of an Ordering for that type if it can then it will pass such value implicitly to the method call for you; again the implicits topic is very broad and deserves its own question.
Now for your particular question, you can just call max or maxOption in the List or Stream and that is all.
Note that max will throw if the List is empty, whereas maxOption returns an Option which will be empty (None) for an empty input; idiomatic Scala favour the latter over the former.
If you really want to use compareTo then you can provide your own Ordering.
scalaList.maxOption(Ordering.fromLessThan[LocalDate]((d1, d2) => d1.compareTo(d2) < 0))
Ordering[A] is a type class which defines how to compare 2 elements of type A. So to compare LocalDates you need Ordering[LocalDate] instance.
LocalDate extends Comparable in Java and Scala conveniently provides instances for Comparables so when you invoke:
Ordering[java.time.LocalDate]
in REPL you'll see that Scala is able to provide you the instance without you needing to do anything (you could take a look at the list of methods provided by this typeclass).
Since you have and Ordering in implicit scope which types matches the Stream's type (e.g. Stream[LocalDate] needs Ordering[LocalDate]) you can call .max method... and that's it.
val processedResult : Stream[LocalDate] = ...
val newestDate: LocalDate = processedResult.max

Scala equivalent of java.util.Collection?

What is the equivalent of java.util.Collection? I first thought Seq is the way to go, but actually it's an ordered set of elements. I mean we have a numeration of elements.
Collection Hierarcy
Traversable is on top above iterable
The picture above is very good looking, but it is not helpful at all in answering the question. (It may be helpful as general reference for other purposes, but not for this purpose.) It is even missing some very important interfaces. So, here is some good old text to try and clear out the confusion:
The Scala equivalent to java.util.Collection is scala.collection.Iterable, despite the mismatch in the name.
You see, scala.collection.Iterable offers the basic functionality of a Java Collection: it has an iterator and a size.
Apparently, what Java calls Iterable Scala calls it Traversable, and then what Java calls Collection Scala calls it Iterable.

Scala objects masked as methods vs actual method (Stream.cons)

I have been going through the Scala Stream collection API and I have noticed that Stream.cons is implemented as an embedded object. What advantage does this have over implementing it as a function? Under what circumstances should one consider using this technique?
Cheers.
As an object, it defines unapply in addition to apply, which let you pattern match on it.

Mock for comprehension in scala

I have this piece of code
for (element <- table.find;
Right(info) = exceptionManager(mapper.getInfoFromDbObject(element)))
yield info
and I would like to unit test it. I want to mock table.find in order to return a sequence of element that I want. I have tried mocking hasNext() and next() methods of Iterator interface but it seems it is not working. Which is the method to mock a for comprehension?
Each for comprehension is translated to map, flatMap, filter method calls. So you should mock at least them.
You can find more information here (for example):
http://www.lambdascale.com/2010/12/the-adventures-of-a-java-developer-in-monadland/
And of course you will find deep explanation in Programming in Scala book.
Edit
But as Dave Griffith said, you can just initialize new Iterator yourself. Here is an example that uses Mockito and ScalaTest:
val table = mock[TableClass]
when(table find) thenReturn Iterator(new ModelObject(1), new ModelObject(2))
Edit 1
As Daniel noticed, filter method is now deprecated in for comprehensions. Instead you should use withFilter. For more information you can look in this thread:
http://scala-programming-language.1934581.n4.nabble.com/Rethinking-filter-td2009215.html#a2009218
and this related SO question:
guide to move from filter to withFilter?
In theory, you should mock the "map" method, but you're probably better off simply having table.find return one of the predefined collection types.

Why does Iterables.find() in Guava throw NoSuchElementException, instead of returning null?

I love Google Guava and use it a lot, but there is one method I always find me writing..
public static <T> T tryFind(Iterable<T> iterable, Predicate<T> predicate){
for(T t : iterable){
if(predicate.apply(t)){
return t;
}
}
return null;
}
To me this seems to be a very useful addition to Iterables (also to Iterators for that matter), so I'm wondering why it's missing. Also, while I can see the point of having a method that throws NoSuchElementException, perhaps to distinguish between finding a null and not finding the element, that situation only comes up if the predicate you are using is
public boolean apply(T t){
return t==null;
}
which doesn't seem to be a common case.
So why did guava designers chose to have this behavior, instead of just returning null if it can't find it?
Here is the javadoc for [Iterables.find()][1]
[1]: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterables.html#find(java.lang.Iterable, com.google.common.base.Predicate)
We're adding another overload of find() which accepts a default value.
Likely because null is a valid return value. Generally speaking, unless there is a good reason to not support null then it should be supported. If it is supported then you have to handle the case where it exists.
Instead of tryFind() you can use filter and check if it returns an empty collection.
I found that always working with collections is cleaner than directly asking objects.
In my opinion, the NoSuchElementException is better than a late and very difficult to debug NPE...
In most cases, when you are searching an object in a "collection", you know that you would probably find it.
If the object you're looking for is not in the "collection", you're facing an exceptional case... According to me, the NoSuchElementException feedback is more explicit than the meaningless "null".
The default value which will be introduced in a future guava release would be an efficient shortcut to treat the exceptionnal case.
Find would make sense if it could not to find rather finding default value.
Optional<T> Iterables.find(Iterable<T>, Predicate<? super T>)