What's the difference between peekOption and headOption in Vavr Collection - java

Here the doc for Vavr List peekOption
https://www.javadoc.io/doc/io.vavr/vavr/0.10.1/io/vavr/collection/List.html#peekOption--
Here the doc of Vavr Traversable headOption
https://www.javadoc.io/doc/io.vavr/vavr/0.10.1/io/vavr/collection/Traversable.html#headOption--
Implémentation seems exactly the same so with that kind of usage i can use both but which is the best..?
MyObject myObject = myJavaCollection.stream()
.filter(SomePredicate::isTrue)
.collect(io.vavr.collection.List.collector()) //Collect to vavr list to have vavr methods availables
.peek(unused -> LOGGER.info("some log"))
.map(MyObject::new)
.peekOption() //or .headOption()
.getOrNull();
So i was wondering what is the différence between those methods.

From the sourcecode of Vavr's List (see https://github.com/vavr-io/vavr/blob/master/src/main/java/io/vavr/collection/List.java) we have:
/**
* Returns the head element without modifying the List.
*
* #return {#code None} if this List is empty, otherwise a {#code Some} containing the head element
* #deprecated use headOption() instead
*/
#Deprecated
public final Option<T> peekOption() {
return headOption();
}
So they do exactly the same, like you say, and since peekOption() is deprecated, headOption() seems to be the one to use.
As for the reason to use one over the other:
It looks like the Vavr List interface defines some stack related methods (like push, pop, peek, etc) to make it easier to use lists as stacks in a convenient way, if you should want that. (For example, you would use peekOption() if you consider the list to be a stack and headOption() otherwise)
These stack-methods are however all deprecated - probably because there are always non-stack methods that can be used instead of them. So they probably backed away from the idea that "a list is also a stack" - maybe because they thought it mixes concepts a bit and makes the interface too big (just a guess). So that must be the reason headOption() is preferred - all the stack-methods are deprecated.
(Normal Java Lists also have stack methods, but that is through an interface, so all lists are also stacks but you can have a stack which is not a list.))

According to their documentation (List and Traversable)
List's peekOption
default Option peekOption()
Returns the head element without modifying the List.
Returns:
None if this List is empty, otherwise a Some containing the head element
Traversable's headOption
default Option headOption()
Returns the first element of a non-empty Traversable as Option.
Returns:
Some(element) or None if this is empty.
They act exactly the same way. They either return the head element or Option.none(). Only their variants head and peek throw an exception if no elements are present. List simply happens to have two methods that behave the same way only because it extends the Traversable interface.

Related

Do all Lists in Java maintain insertion order

The List javadocs mentions that Lists are ordered. However, I cannot see anything specifying the nature of the ordering. Can we rely on lists e.g. ArrayList and LinkedList maintaining insertion order?
I am asking about the instance where we do not call set or sort.
However, I cannot see anything specifying the nature of the ordering.
Funnily enough, it's mentioned in the second sentence of its documentation:
The user of this interface has precise control over where in the list each element is inserted.
Without calling List#set or List#sort, the only methods that will add elements to the List are List#add and List#addAll, both of which append them to the end (unless you call one of the overloaded methods and specify an index); you can also add elements to the List via its ListIterator.
If List did not maintain insertion order, it would have mentioned it in its documentation. If you're still unsure, feel free to look over the source code, which is available online.

Java: Curious ImmutableList add

I don't understand this method implementation. It's
public static <T> List<T> add(List<T> list, T element) {
final int size = list.size();
if (size == 0) {
return ImmutableList.of(element);
} else if (list instanceof ImmutableList) {
if (size == 1) {
final T val = list.get(0);
list = Lists.newArrayList();
list.add(val);
} else {
list = Lists.newArrayList(list);
}
}
list.add(element);
return list;
}
Why not a straightforward list.add(element)?
The code is implementing adding to the list that's given. If the input list is an ImmutableList, it first creates a mutable list (since otherwise it can't add to it) and copies the elements to it. If it's not, it just uses the existing list.
It's a bit odd that it returns an ImmutableList if the list passed in is empty, but a (mutable) ArrayList if it's given a non-empty ImmutableList to add to, but perhaps that makes sense in the broader context of where and how it's used. But that inconsistency is definitely something I'd query in a code review.
Addition for ImmutableList
Why not a strightforward list.add(element)?
You can't call that method if the given list is immutable. Actually you can but usually such a method will then throw an UnsupportedOperationException. The documentation of Guavas ImmutableList#add says
Deprecated. Unsupported operation.
Guaranteed to throw an exception and leave the list unmodified.
However the goal of the method seems to be to also support addition for ImmutableList by creating a mutable clone. So a straightforward implementation would be:
public static <T> List<T> add(List<T> list, T element) {
if (list instanceof ImmutableList) {
// Create mutable clone, ArrayList is mutable
list = Lists.newArrayList(list);
}
list.add(element);
return list;
}
Other stuff
Note that the type may change. While the input may be an ImmutableList, the output definitely is not.
You could keep the type by creating a temporary clone, adding to it (as shown) and then again wrap some ImmutableList around. However that doesn't seem to be a goal of this method.
Also note that the method in same cases may add something to the given list and in some create a new instance instead. So the caller of the method must be aware of the method sometimes changing his argument and sometimes not. For me this is a very odd behavior, it definitely must be highlighted in the documentation but I would not recommend doing stuff like that.
It seems that another goal of the method is to keep the list immutable if it was empty at method call. This is a bit strange but probably highlighted in its documentation. Therefore they add this call:
if (size == 0) {
return ImmutableList.of(element);
}
Besides that they do some minor stuff by calling
Lists.newArrayList();
instead of
Lists.newArrayList(list);
if the list is currently of size 1. However I'm not sure why they do this step. In my opinion they could just leave it the way it was.
So all in all I would probably implement such a method as
/**
* Creates a new list with the contents of the given list
* and the given element added to the end.
*
* <T> The type of the lists elements
*
* #params list The list to use elements of, the list will not be changed
* #params element The element to add to the end of the resulting list
*
* #return A new list with the contents of the given list and
* the given element added to the end. If the given list was
* of type {#link ImmutableList} the resulting list will
* also be of type {#link ImmutableList}.
**/
public static <T> List<T> add(List<T> list, T element) {
List<T> result;
// Create a Stream of all elements for the result
Stream<T> elements = Stream.concat(list.stream(), Stream.of(element));
// If the list was immutable, make the result also immutable
if (list instanceof ImmutableList) {
result = ImmutableList.of(elements.toArray(T[]::new));
} else {
result = elements.collect(Collectors.toList());
}
return result;
}
By that you won't ever change the argument list and you will also keep the list ImmutableList if it was. Using the Stream#concat method makes things a bit more efficient here (it is a lazy method), otherwise we would need to create temporary clones in between.
However we do not know which goals your method has, so probably in the context of your specific method what it does it makes more sense.
This method is an anti-pattern, and should not be used. It munges mutable and immutable data structures, providing the worst of both implementations.
If you're using an immutable data structure you should make that clear in your types - casting to List loses that important context. See the "Interfaces" not implementations section of ImmutableCollection.
If you're using a mutable data you should avoid doing linear-time copies and instead take advantage of the data structure's mutability (carefully).
It generally does not make sense to use the two types interchangeably - if you want to add things to an existing collection use a mutable collection you own. If you intend for the collection to be immutable, don't try to add things to it. This method discards that intent and will lead to runtime errors and/or reduced performance.
The reason that this method is not "a straightforward list.add(element)" is because this method is designed to be able to add elements to ImmutableLists. Those are, quite obviously, immutable (if you look, their native add method throws an UnsupportedOperationException) and so the only way to "add" to them is to create a new list.
The fact that the newly returned list is now mutable is a strange design decision and only a wider context or input from the code's author would help solve that one.
The special case where an empty input list will return an immutable list is another strange design decision. The function would work fine without that conditional branch.
Because this method returns a copy of the list, you should be careful to assign the result to something, probably the original variable:
myList = TheClass.add(myList, newElement);
and note that the following usage will effectively do nothing:
TheClass.add(myList, newElement);

Java collection interface that guarantees no duplicates as well as preservation of insertion order

Is there a java collection interface that guarantees no duplicates as well as the preservation of insertion order at the same time?
This is exactly what LinkedHashSet is doing? However, I am wondering if there is also an interface guaranteeing the same thing in order to avoid direct dependency on some specific class?
SortedSet is referring only to the natural order (and is not implemented by LinkedHashSet).
Essentially, I am looking for an interface that would indicate that the iteration order of elements is significant (and at the same time it contains no duplicates, i.e., List obviously would not apply).
Thanks!
UPDATE this question is not asking for an implementation or a data structure (as in the question to which this was marked as a duplicate). As several people pointed out as clarification, I am looking for an interface that demands both properties (no duplicates and significant order) in its contract. The application for this would be that I can return objects of this type to clients without promising any specific implementation.
UPDATE 2 Moreover, the related question specifically asks for preserving duplicates in contrast to this question. So I am pretty certain it is not a duplicate.
No interface in the JDK collections provides that.
You could try to build it by combining Set and List. Any collection implementing Set should not allow duplicate elements, and any collection implementing List should maintain order.
But then, no class in the JDK collection implements both Set and List. Because unfortunately LinkedHashSet does not implement List.
Of course, you could build one implementation easily by wrapping a LinkedHashSet (by composition patter, not by derivation) and adding a get(int i) method, or by wrapping an ArrayList (again by composition) and throwing an IllegalArgumentException when trying to add a new element.
The most tricky part IMHO would be the addAll method as both interfaces define it with different semantics (emphasize mine) :
Set: Adds all of the elements in the specified collection to this set if they're not already present
List : Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator
As you cannot meet both requirements is source collection contains duplicates, my advice would be that addAll throws an IllegalArgumentException in that case, or more simply that it always throw an UnsupportedOperationException as addAll is an optional operation for both interfaces

How to pop items from a collection in Java?

Is there a method in JDK or apache commons to "pop" a list of elements from a java.util.List? I mean, remove the list of elements and return it, like this method:
public Collection pop(Collection elementsToPop, Collection elements) {
Collection popped = new ArrayList();
for (Object object : elementsToPop) {
if (elements.contains(object)) {
elements.remove(object);
popped.add(object);
}
}
return popped;
}
If you're looking for a stack-like structure I suggest accepting a Deque (LinkedList is the most common implementation) instead of a Collection.
If you don't actually need to treat it as a stack, just get an iterator from the Collection and use the remove() method:
for (Iterator<SomeType> it = elements.iterator(); it.hasNext(); ) {
SomeType e = it.next();
it.remove();
popped.add(e);
}
Do note that remove is an optional operation, and some implementations may throw an UnsupportedOperationException (for example, the iterator returned by a Collection from Collections.unmodifiable...() will).
Edit: After looking more closely at your question, I think you just need this:
elements.removeAll(elementsToRemove);
If your main point is you need to know exactly which elements were actually popped, I think you're stuck with your original code.
There is no such method in the standard JDK-provided methods. Apache Commons provides the ListUtils.subtract() method.
Edit: As other answerers have noted, your use of the term pop is nonstandard. Usually,
The pop operation removes an item from the top of [a stack]
Wikipedia has a nice description of stacks.
I guess no, because you definition of 'pop' operation is highly non-standard. Usually it takes no arguments (except collection itself) and returns and removes the top-most one.
But once you noted apache commons, this would achieve the same effect as your code.
Collection result = CollectionUtils.intersection(a, b);
a.removeAll(b);
edit
http://commons.apache.org/collections/api-release/index.html
Linked List provides the functionality as you require, provides a push and pop method.
Refer to the documentation as provided:
There isn't a method exactly like what you are asking for, but it looks like you are already pretty close with your code.
Some suggestions:
Consider using removeAll(object) instead of remove(object) if elements is an arbitrary collection since you may need to remove duplicates e.g. if elements is a list.
contains() is slow for some collection types (e.g. lists) since it needs to traverse the entire data structure. Given that this is in your inner loop you are at risk of O(n^2) performance issues. If you can make the algorithm work with a HashSet or HashMap then contains() will by O(1) and your algorithm will be much more efficient.

Do containsAll() and retainAll() in the Collection interface address cardinality?

In Java, the containsAll and retainAll in the AbstractCollection class explicitly state that cardinality is not respected, so in other words it does not matter how many instances of a value are on each side. Since all Java collections in the standard library extend AbstractCollection, it is assumed that all of them work the same.
However, the documentation of these methods in the Collection interface does not say anything. Is one supposed to infer from AbstractCollection, or was this left unspecified on purpose to allow one to define collections that work differently?
For example, Bag in apache-collections explicitly states that it does respect cardinality, and claims that it violates the contract of the version from Collection (even though it doesn't really).
So, what are the semantics of these operations in Collection rather than in AbstractCollection?
Edit: Tho those who are wondering about why I would care, it's because as part of my Ph.D. work I demonstrated that developers don't expect the conformance violation in Apache, but I'm trying to understand why the Collection interface was left so ambiguous.
The javadocs for containsAll (in Collection) say:
Returns: true if this collection
contains all of the elements in the
specified collection
and for retainAll (in Collection):
Retains only the elements in this
collection that are contained in the
specified collection (optional
operation). In other words, removes
from this collection all of its
elements that are not contained in the
specified collection.
I read containsAll's contract to mean that calling a.containsAll(b) will return true, if and only if, calling a.contains(bElem) for each element bElem in b would return true. I would also take it to imply that a.containsAll(someEmptyCollection) would also return true. As you state the javadocs for AbstractCollection more explicitly state this:
This implementation iterates over the
specified collection, checking each
element returned by the iterator in
turn to see if it's contained in this
collection. If all elements are so
contained true is returned, otherwise
false.
I agree that the contact for Collection for containsAll sould be more explicit to avoid any possiblity for confusion. (And that the reading of the javadocs for AbstractCollection should NOT have been necessary to confirm ones understanding of Collection)
I would not have made an assumption with regard to number of duplicate elements after a call to retainAll. The stated contract in Collection (by my reading) doesn't imply either way how duplicates in either collection would be handled. Based on my reading of retainAll in collection multiple possible results of a.retainAll(b) are all reasonable:
result contains 1 of each element that has at least one copy in both a and b
result contains each element (including duplicates) that was in a, except those that are not in b
or even, result contains somewhere between 1 and the number of copies found in a of each element in a, except those not in b.
I would have expected either #1 or #2, but would assume any of the the three to be legal based on the contract.
The javadocs for AbstractCollection confirm that it uses #2:
This implementation iterates over this
collection, checking each element
returned by the iterator in turn to
see if it's contained in the specified
collection. If it's not so contained,
it's removed from this collection with
the iterator's remove method
Although since this isn't in my reading of the original Collection interface's contract, I wouldn't necessarily assume the behavior of Collection to generally be this way.
Perhaps you should consider submitting suggested updates to the JavaDoc once you're done.
As to 'why the Collection interface was left so ambiguous' - I seriously doubt it was intentionally done - probably just something that wasn't given its due priority when that part of the API's were being written.
I don't think Collection defines it this way or the other, but it simply became sort of a convention to follow AbstractCollection behavior, for example google-collections do: see their Multiset documentation (Multiset is what they call a Bag)

Categories