Find the root of a hierarchy, using Optional - java

I have a tree hierarchy of types that are aware of their children, but not their parents. Now I am creating an external registry that provides the opposite path, from the outside:
public interface Registry<X>{
Optional<X> parent(X node);
}
Now I'd like to implement a method in that interface, that gets the root note of this hierarchy from any given node (the root node can be the node passed in or any ancestor).
I got this far:
default X root(X node) {
X current = node;
for (Optional<X> opt = Optional.of(current);
opt.isPresent();
opt = opt.flatMap(this::parent)) {
if (opt.isPresent()) {
current = opt.get();
}
}
return current;
}
While this works, it feels kinda clumsy. Optional.isPresent() is called twice, and the variable current is re-assigned. Is there any way I can make this more elegant and functional?

I'm thinking of
default X root(X node) {
X root = node;
for (Optional<X> parentOpt = parent(root); parentOpt.isPresent(); root = parentOpt.get())
;
return root;
}
I don't like dealing with null arguments. So we defer to parent's implementation, which you'll probably document as returning an empty Optional on null argument.
If the argument is null, we'll also return null.
If the argument is not null, we save its value in root and start looping. We get its potential parent. If it's present, we update root, and retry. Otherwise, we break, and return the last saved value in root, since that's as far as we got.
That clumsy feeling, I think, comes from the initial Optional around node. I don't think you need that.

The answer by #Sotirios is concise and more than good enough.
You implemented an Iterator in your attempt at a solution and my solution is to implement it as a Spliterator/Stream. It's probably overly complicated for your particular question, but it could be useful elsewhere for your library, or it could be useful for someone else browsing stackoverflow.
public class ParentSpliterator<T> implements Spliterator<T> {
private final Registry<T> registry;
private Optional<T> currentNodeOpt;
public ParentSpliterator(Registry<T> registry, T startNode) {
this.registry = registry;
this.currentNodeOpt = Optional.of(startNode);
}
#Override
public boolean tryAdvance(Consumer<? super T> action) {
if (!currentNodeOpt.isPresent()) {
return false; // stream is empty
} else {
T currentNode = currentNodeOpt.get();
action.accept(currentNode);
currentNodeOpt = registry.parent(currentNode);
return true;
}
// // Alternative implementation (more Stream-ish):
// return currentNodeOpt.map(node -> {
// action.accept(node);
// currentNodeOpt = registry.parent(node);
// return node;
// }).isPresent();
}
#Override
public Spliterator<T> trySplit() {
return null; // Cannot be split.
}
#Override
public long estimateSize() {
return Long.MAX_VALUE; // No quick way to estimate size.
}
#Override
public int characteristics() {
return Spliterator.ORDERED; // maybe others?
}
public static void main(String[] args) {
Registry.CountDownRegistry cdr = new Registry.CountDownRegistry();
ParentSpliterator<Integer> parentSpliterator = new ParentSpliterator<>(cdr, 3);
Stream<Integer> stream = StreamSupport.stream(parentSpliterator, false);
//stream.forEach(System.out::println);
// Using a reduce to pick the last element of the Stream:
Integer root = stream.reduce((node, nextNode) -> nextNode).get();
System.out.println(root);
}
}
And you need this utility class to get the example to work:
public interface Registry<X> {
Optional<X> parent(X node);
public static class CountDownRegistry implements Registry<Integer> {
#Override
public Optional<Integer> parent(Integer node) {
if (node > 0) {
return Optional.of(node - 1);
} else {
return Optional.empty();
}
}
}
}

Guava and JDK stream versions below, but the absolute winner is JavaSlang. I love it!
import javaslang.collection.Stream;
import java.util.Optional;
// ...
default X root(X node) {
return Stream.iterate(Optional.of(node),
t -> t.flatMap(this::parent)
).takeWhile(Optional::isPresent)
.last()
.orElseThrow(NoSuchElementException::new);
}
The Stream.iterate() method is exactly what I'm missing in the two other versions.
Guava:
First we'll create a helper class called Optionals:
// to avoid misunderstandings:
import java.util.Optional;
import java.util.function.Function;
import com.google.common.collect.AbstractIterator;
public final class Optionals {
private Optionals(){}
/**
* Given an instance of type T and a function from T to Optional<T>,
* return an Iterable<T>. This Iterable will keep returning values
* by repeatedly applying the supplied function until the returned Optional
* is not present.
*/
public static <T> Iterable<T> stream(
final T start, final Function<T, Optional<T>> increment) {
return () -> new AbstractIterator<T>() {
Optional<T> current = Optional.of(start);
#Override
protected T computeNext() {
if (!current.isPresent()) return endOfData();
final T data = current.get();
current = current.flatMap(increment);
return data;
}
};
}
}
This is of course even more boilerplate, but that's re-usable, and now we can write the interface method in a concise way:
default X root(final X node) {
return Iterables.getLast(Optionals.stream(node, this::parent));
}
Obviously it would be possible to implement this without Guava, but it would be a lot messier.
Java 8 Stream version:
public final class Streams {
private Streams(){}
/**
* Given an instance of type T and a function from T to Optional<T>,
* return a Stream<T>. This Stream will keep returning values by
* repeatedly applying the supplied function until the returned Optional
* is not present.
*/
public static <X> Stream<X> stream(
final X start, final Function<X, Optional<X>> increment) {
return StreamSupport.stream(
new Spliterator<X>() {
Optional<X> next = Optional.ofNullable(start);
#Override
public boolean tryAdvance(final Consumer<? super X> action) {
final boolean present = next.isPresent();
if (present) action.accept(next.get());
next = next.flatMap(increment);
return present;
}
#Override
public Spliterator<X> trySplit() { return null; }
#Override
public long estimateSize() { return Long.MAX_VALUE; }
#Override
public int characteristics() { return Spliterator.ORDERED; }
}, false
);
}
Which leads to this code:
default X root(final X node) {
return Streams.stream(node, this::parent)
.reduce((left, right) -> right)
.orElseThrow(NoSuchElementException::new);
}

I think you're pretty close already with the loop you tried. It can be simplified a bit since the loop body is only executed if the loop condition is true, so you don't have to retest opt.isPresent within the loop. You can save a variable if you reuse the node parameter. (I know, it's a style thing.) The flatMap call in the increment part doesn't buy you much because you know that opt is present at that point; you might as well just call parent on the result of opt.get while assigning node while you're at it. This gives:
default X root(X node) {
for (Optional<X> opt = Optional.of(node); opt.isPresent(); opt = parent(node = opt.get()))
;
return node;
}
You pretty much have to assume that node is non-null, so you can move the parent call into the loop condition, simplifying things a bit:
default X root(X node) {
for (Optional<X> opt; (opt = parent(node)).isPresent(); node = opt.get())
;
return node;
}
Java 9 will have a new three-arg Stream.iterate factory that lets you create a leaf-to-root stream of nodes quite conveniently. The three arguments are just like the three statements of a for-loop, except they can't have side effects. You can transliterate your original for-loop into a stream as follows:
default Stream<X> stream(X node) {
return Stream.iterate(Optional.of(node),
Optional::isPresent,
op -> op.flatMap(this::parent))
.map(Optional::get);
}
Finally, there is this:
default X root(X node) {
return Optional.of(node).flatMap(this::parent).map(this::root).orElse(node);
}
There are several things of note regarding this technique.
It violates one of the style rules for Optional that I've been espousing, in particular this one: "#4: It's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value." (link)
It's recursive, which means it can blow your stack if your hierarchy is too deep.
Your coworkers will shun you if you use this technique.
I don't recommend writing code like this, but I wanted to put it out there before somebody else did. :-)

Related

Cleaning up an Iterable when not all elements are read

Getting my feet wet on RxJava. I have a class that implements Iterable I want to convert to an Observable. Using Observable.from() seems easy. However I need to setup and tear-down the code that provides me the individual entries (the next() in the iterator.
When I run through the entire sequence, that's easy. I added the call to the hasNext() function and when there is no next I run the teardown. However one of the very promising operators I want to use is take(someNumber). If the taking stops before the Iterator runs out of items, the cleanup code never runs.
What can I do to get my cleanup running? If using something else than from(Iterable), I'm OK with that. I'm stuck on Java6 for now. To illustrate my predicament I created a minimal sample:
Update: Based on feedback not to mix Iterator and Iterable together, I updated the code below. To understand the original answers, the original code is in that gist.
Updated Test code (still bad):
import rx.Observable;
import rx.functions.Action0;
import rx.functions.Action1;
/**
* #author stw
*
*/
public class RXTest {
/**
* #param args
*/
public static void main(String[] args) {
ComplicatedObject co = new ComplicatedObject();
Observable<FancyObject> fancy = Observable.from(co);
// if the take is less than the elements cleanup never
// runs. If you take the take out, cleanup runs
fancy.take(3).subscribe(
new Action1<FancyObject>() {
public void call(FancyObject item) {
System.out.println(item.getName());
}
},
new Action1<Throwable>() {
public void call(Throwable error) {
System.out.println("Error encountered: " + error.getMessage());
}
},
new Action0() {
public void call() {
System.out.println("Sequence complete");
}
}
);
}
}
The fancy object:
import java.util.Date;
import java.util.UUID;
/**
* #author stw
*
*/
public class FancyObject {
private String name = UUID.randomUUID().toString();
private Date created = new Date();
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return this.created;
}
public void setCreated(Date created) {
this.created = created;
}
}
The iterator:
import java.util.Iterator;
/**
* #author stw
*
*/
public class FancyIterator implements Iterator<FancyObject> {
private final ComplicatedObject theObject;
private int fancyCount = 0;
public FancyIterator(ComplicatedObject co) {
this.theObject = co;
}
public boolean hasNext() {
return this.theObject.hasObject(this.fancyCount);
}
public FancyObject next() {
FancyObject result = this.theObject.getOne(this.fancyCount);
this.fancyCount++;
return result;
}
}
The Iterable:
import java.util.Iterator;
import java.util.Vector;
/**
* #author stw
*
*/
public class ComplicatedObject implements Iterable<FancyObject> {
private boolean isInitialized = false;
Vector<FancyObject> allOfThem = new Vector<FancyObject>();
public Iterator<FancyObject> iterator() {
return new FancyIterator(this);
}
public boolean hasObject(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
return (whichone < this.allOfThem.size());
}
public FancyObject getOne(int whichone) {
if (!this.isInitialized) {
this.setupAccesstoFancyObject();
}
if (whichone < this.allOfThem.size()) {
return this.allOfThem.get(whichone);
}
// If we ask bejond...
this.isInitialized = false;
this.teardownAccessToFancyObjects();
return null;
}
private void setupAccesstoFancyObject() {
System.out.println("Initializing fancy objects");
for (int i = 0; i < 20; i++) {
this.allOfThem.addElement(new FancyObject());
}
this.isInitialized = true;
}
private void teardownAccessToFancyObjects() {
System.out.println("I'm doing proper cleanup here");
}
}
But the real question (thx #Andreas) seem to be:
What construct can I use to create an Observable when the underlying code need setup/teardown, especially when one expects that not all elements are pulled. The Iterable just was my first idea
Update 2: Based on Dave's answer I created a gist with my working solution. The iterator isn't perfect, but it's a start.
Observable.using is used for tearing down on termination (completion or error) or unsubscription. To use it you need to make the tear-down code accessible so that your source observable can look like this:
source = Observable.using(
resourceFactory,
observableFactory,
resourceDisposer);
With your code it might look like this:
source = Observable.using(
() -> new ComplicatedObject(),
co -> Observable.from(co),
co -> co.tearDown());
If you want that kind of control you need to separate the implementation of Iterable from Iterator. Iterable means the class can provide an Iterator that is meaningful in whatever fashion makes sense for the class.
However, if you implement Iterator in the same class, then you are stuck with only ever having one Iterator for each instance of ComplicatedObject. The correct approach is to implement
class FancyObjectIterator implements Iterator<FancyObject>
{
...
}
separately from ComplicatedObject so you can merely discard the partially-used iterators when you are done with them. ComplicatedObject should implement only Iterable<FancyObject>.
If you object to that approach because the iterator has more state that needs special cleanup, then something is wrong with your design. The only state an Iterator should be aware of is the current position in the base "collection", for a very loose definition of "collection" and "position" since the concept of an iterator can apply to much more than typical collections.
You cannot implement Iterator and Iterable at the same time, since Iterable.iterator() must return a new Iterator or every call.
Code is allowed to iterate the same Iterable multiple times in parallel.
Example: An over-simplified way to find duplicate elements in an Iterable:
Iterable<MyObject> myIterable = ...;
for (MyObject myObj1 : myIterable) {
for (MyObject myObj2 : myIterable) {
if (myObj1 != myObj2 && myObj1.equals(myObj2)) {
// found duplicate
}
}
}
The enhanced for loops used here will each use an Iterator.
As you can see, each Iterator must maintain it's own independent position. Therefore, the iterator() method needs to return a new object, with it's own state.
And for your question on cleanup code, an Iterator does not have a close() method. Iterator state should not require cleanup. If they absolutely must, a finalizer can do it, but finalizers may take a very long time to be invoked. The general recommendation for finalizers is: DON'T.

do-while with Java8-Optional

I'm frequently using the do-while-checkNextForNull-getNext looping pattern (don't know if there is an official name for it) in some of my projects. But in Java8, the use of Optional is considered as cleaner code than checking for null references in client-code. But when using Optional in this looping pattern, the code gets a bit verbose and ugly, but because Optional has some handy methodS, I would expect that there must exist a cleaner way than the one I came up with below.
Example:
Given the following class.
class Item {
int nr;
Item(nr) {
this.nr = nr;
// an expensive operation
}
Item next() {
return ...someCondition....
? new Item(nr + 1)
: null;
}
}
In which the first item always has nr==1 and each item determines the next item, and you don't want to create unnecessary new items.
I can use the following looping do-while-checkNextForNull-getNext pattern in client-code:
Item item = new Item(1);
do {
// do something with the item ....
} while ((item = item.next()) != null);
With Java8-Optional, the given class becomes:
class Item {
....
Optional<Item> next() {
return ...someCondition....
? Optional.of(new Item(nr + 1))
: Optional.empty();
}
}
And then the do-while-checkNextForNull-getNext looping pattern becomes a bit ugly and verbose:
Item item = new Item(1);
do {
// do something with the item ....
} while ((item = item.next().orElse(null)) != null);
The orElse(null)) != null part feels uncomfortable.
I have looked for other kind of loops, but haven't found a better one. Is there a cleaner solution?
Update:
It is possible to use a for-each loop while at the same time avoiding null-references (the use of null-references is considered as a bad practice). This solution has been proposed by Xavier Delamotte, and doesn't need Java8-Optional.
Implementation with a generic iterator:
public class Item implements Iterable<Item>, Iterator<Item> {
int nr;
Item(int nr) {
this.nr = nr;
// an expensive operation
}
public Item next() {
return new Item(nr + 1);
}
public boolean hasNext() {
return ....someCondition.....;
}
#Override
public Iterator<Item> iterator() {
return new CustomIterator(this);
}
}
and
class CustomIterator<T extends Iterator<T>> implements Iterator<T> {
T currentItem;
boolean nextCalled;
public CustomIterator(T firstItem) {
this.currentItem = firstItem;
}
#Override
public boolean hasNext() {
return currentItem.hasNext();
}
#Override
public T next() {
if (! nextCalled) {
nextCalled = true;
return currentItem;
} else {
currentItem = currentItem.next();
return currentItem;
}
}
}
Then client code becomes very simple/clean:
for (Item item : new Item(1)) {
// do something with the item ....
}
Although this may be seen as a violation of the Iterator contract because the new Item(1) object is included in the loop, whereas normally, the for loop would immediately call next() and thus skipping the first object. In other words: for the first object, next() is violated because it returnS the first object itself.
You can do something like this :
Optional<Item> item = Optional.of(new Item(1));
do {
Item value = item.get();
// do something with the value ....
} while ((item = value.next()).isPresent());
or (to avoid the extra variable) :
Optional<Item> item = Optional.of(new Item(1));
do {
// do something with item.get() ....
} while ((item = item.get().next()).isPresent());
in Java8, the use of Optional is considered as cleaner code than checking for null references in client-code
No, it is the other way around: Optional can be used where it helps write cleaner code. Where it doesn't, just stick to the old idiom. Do not feel any pressure to use it if your existing idiom looks fine—and it does, in my opinion. As an example, this would be good usage of the Optional:
item.next().map(Object::toString).ifPresent(System.out::println);
Since you need to break out of the loop on the first non-present Optional, this doesn't really help.
However, I assume your true interest is more general: leveraging the features of Java 8 for your code. The abstraction you should pick is the Stream:
itemStream(() -> new Item(1)).forEach(item -> { ... all you need ... });
And, naturally, you can now go wild with stream processing:
itemStream(() -> new Item(1)).filter(item.nr > 3).mapToInt(Item::nr).sum();
This is how you would construct the stream:
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class ItemSpliterator extends Spliterators.AbstractSpliterator<Item>
{
private Supplier<Item> supplyFirst;
private Item lastItem;
public ItemSpliterator(Supplier<Item> supplyFirst) {
super(Long.MAX_VALUE, ORDERED | NONNULL);
this.supplyFirst = supplyFirst;
}
#Override public boolean tryAdvance(Consumer<? super Item> action) {
Item item;
if ((item = lastItem) != null)
item = lastItem = item.next();
else if (supplyFirst != null) {
item = lastItem = supplyFirst.get();
supplyFirst = null;
}
else return false;
if (item != null) {
action.accept(item);
return true;
}
return false;
}
public static Stream<Item> itemStream(Supplier<Item> supplyFirst) {
return StreamSupport.stream(new ItemSpliterator(supplyFirst), false);
}
}
With this you are a tiny step away from the ability to seamlessly parallelize your computation. Since your item stream is fundamentally sequential, I suggest looking into my blog post on this subject.
Just add the loop support to your API:
class Item {
int nr;
Item(int nr) {
this.nr = nr;
// an expensive operation
}
public void forEach(Consumer<Item> action) {
for(Item i=this; ; i=new Item(i.nr + 1)) {
action.accept(i);
if(!someCondition) break;
}
}
public Optional<Item> next() {
return someCondition? Optional.of(new Item(nr+1)): Optional.empty();
}
}
Then you can simply iterate via lambda expression
i.forEach(item -> {whatever you want to do with the item});
or method references
i.forEach(System.out::println);
If you want to support more sophisticated operations than just forEach loops, supporting streams is the right way to go. It’s similar in that your implementation encapsulates how to iterate over the Items.
Dropping another alternative here that is available since Java 9.
Stream.iterate(new Item(1), Item::hasNext, Item::next)
.forEach(this::doSomething)
Where doSomething(Item item) is the method that does something with the item.
Since this is related to some kind of design i come up with below design.
Create interface which support to provide optional next.
public interface NextProvidble<T> {
Optional<T> next();
}
Item implement NextProvidble interface.
public class Item implements NextProvidble<Item> {
int nr;
Item(int nr) {
this.nr = nr;
// an expensive operation
}
#Override
public Optional<Item> next() {
return /*...someCondition....*/ nr < 10 ? Optional.of(new Item(nr + 1)) : Optional.empty();
}
#Override
public String toString() {
return "NR : " + nr;
}
}
Here i use /...someCondition..../ as nr < 10
And new class for Custom Do While as below.
public abstract class CustomDoWhile<T extends NextProvidble<T>> {
public void operate(T t) {
doOperation(t);
Optional<T> next = t.next();
next.ifPresent( nextT -> operate(nextT));
}
protected abstract void doOperation(T t);
}
Now what you have to done in your client code.
new CustomDoWhile<Item>() {
#Override
protected void doOperation(Item item) {
System.out.println(item.toString());
}
}.operate(new Item(1));
It may very clear.
Please add your thoughts.

Guava Supplier : transforming a collection with each element's own function

Let's say I have a Node class that has a Function as an instance variable.
public class Node {
private Function<Node, Double> function;
...
I have a List of these Nodes:
List<Node> nodes = Lists.newLinkedList();
nodes.add(new Node(someFunction));
nodes.add(new Node(someOtherFunction));
I can do this:
public Collection<Double> getValues() {
SomeFunction f = new SomeFunction();
return Collections2.transform(nodes, f);
}
Sure enough, transform iterates over the nodes List and applies the function f to each element like mapcar.
What I'm trying to do is to have transform use the function that each node element has.
So I though that the Supplier would help.
class NodeSupplier implements Supplier<Node> {
Iterator<Node> iterator;
NodeSupplier(Iterable p) {
iterator = Iterators.cycle(p);
}
#Override
public Node get() {
return iterator.next();
}
}
Then a Function to get a Node.
class SupplierGetter implements Function<Supplier<Node>, Node> {
#Override
public Node apply(Supplier<Node> from) {
return from.get();
}
}
Then compose them:
FunctionGetter fg = new FunctionGetter();
NodeSupplier sup = new NodeSupplier(this); // the this class is Iterable
Supplier<Function<Node, Double>> supplier = Suppliers.compose(fg, sup);
But then it gives me a type mismatch when I try to use it:
Collections2.transform(nodes, supplier);
it wants suppler.get() which is called once.
Collections2.transform(nodes, supplier.get());
Is there an easier way?
I saw mention of
Suppliers.supplierFunction()
but that seem s to not exist in verison r09.
I'm confused by what you're trying to do... Supplier doesn't seem useful here. Each Node has its own Function. You want to transform a collection of Nodes by applying each Node's Function to itself. So why not just give the Node class some method:
// may want a better name
public Double applyFunction() {
return function.apply(this);
}
Then you'd just transform using a Function like this:
public Double apply(Node node) {
return node.applyFunction();
}
Apart from the fact that I also have my doubts about what you are trying to do, the following should achieve what you are asking for:
class Node {
private Function<Node, Double> function;
private static Function<Node,Double> applyFunction = new Function<Node,Double>() {
#Override
public Double apply(final Node input) {
return input.function.apply(input);
}
};
public static Iterable<Double> transform(final Iterable<Node> nodes) {
return Iterables.transform(nodes, applyFunction);
}
}
There is a third way to do this without modifying the Node class, if we suppose that Node exposes its function through a public getter.
Using an anonymous class :
public Collection<Double> getValues() {
return Collections2.transform(nodes, new Function<Node, Double>() {
#Override public Double apply(Node node) {
return node.getFunction().apply(node);
}
});
}
Using the enum singleton pattern (which I prefer, since it's clearer) :
public Collection<Double> getValues() {
return Collections2.transform(nodes, ApplyNodeFunction.INSTANCE);
}
/**
* A {#link Function} that applies the {#link Node}'s own function on itself.
*/
private enum ApplyNodeFunction implements Function<Node, Double> {
INSTANCE;
#Override public Double apply(Node node) {
return node.getFunction().apply(node);
}
}
The key to my question was this phrase: "So I thought that the Supplier would help." The answer is that it doesn't. I was trying to find a use for it - outside of Map creation which seems to be its main use. There was that one Suppliers method I mentioned but it seems to be MIA. Perhaps this could be an RFI for tranform be overloaded to take an Iterable as the second parameter

Provide an iterator over the contents of two lists simultaneously?

Suppose I have this:
public class Unit<MobileSuit, Pilot> {
...
List<MobileSuit> mobileSuits;
List<Pilot> pilots;
...
}
And I would like to iterate through the pair of each in the simplest way outside of that class. How should I go about doing that? I thought about doing this:
public class Unit<MobileSuit, Pilot> {
...
Iterator<MobileSuit> iteratinMechas;
Iterator<Pilot> iteratinPeople;
class IteratorCustom<MobileSuit, Pilot> implements Iterator {
public boolean hasNext() {
return iteratinMechas.hasNext() && iteratinPeople.hasNext();
}
public void remove() {
iteratinMechas.remove();
iteratinPeople.remove();
}
public Object next() {
// /!\
}
}
public Iterator iterator() {
return new IteratorCustom<MobileSuit, Pilot>(mobileSuits, pilots);
}
}
Something along those lines.
Anyway, the problem is that I can't really return just a single object from next(), and I also can't have a Iterator take more than one type. So, any thoughts?
Also, I can't make a new class to combine MobileSuit and Pilot. I need to keep them separate, even though I'm iterating through both at a time. The reason is that there might be Mobile Suits that have no pilots, and I'm not sure how to fix that by keeping them at the same class. This class needs to be processed in other places, so I'd have to unify a interface around that and a lot of other stuff. Basically, assume MobileSuit and Pilot need to be separated.
Anyway, the problem is that I can't really return just a single object from next(), and I also can't have a Iterator take more than one type. So, any thoughts?
Obviously you are going to need a light-weight "pair" class. This is roughly analogous to the Map.Entry inner class.
Here's a rough cut at a generic solution:
public class ParallelIterator <T1, T2> implements Iterator<Pair<T1, T2>> {
public class Pair<TT1, TT2> {
private final TT1 v1;
private final TT2 v2;
private Pair(TT1 v1, TT2 v2) { this.v1 = v1; this.v2 = v2; }
...
}
private final Iterator<T1> it1;
private final Iterator<T2> it2;
public ParallelIterator(Iterator<T1> it1, Iterator<T2> it2) {
this.it1 = it1; this.it2 = it2;
}
public boolean hasNext() { return it1.hasNext() && it2.hasNext(); }
public Pair<T1, T2> next() {
return new Pair<T1, T2>(it1.next(), it2.next());
}
...
}
Note: this doesn't explicitly deal with cases where the lists have different lengths. What will happen is that extra elements at the end of the longer list will be silently ignored.
This is copied+edited from Stephen C's answer. Feel free to use:
public class Pair<T1, T2> {
private final T1 v1;
private final T2 v2;
Pair(T1 v1, T2 v2) {
this.v1 = v1;
this.v2 = v2;
}
public T1 first(){
return v1;
}
public T2 second(){
return v2;
}
}
public class ParallelIterator <T1, T2> implements Iterator<Pair<T1, T2>> {
private final Iterator<T1> it1;
private final Iterator<T2> it2;
public ParallelIterator(Iterator<T1> it1, Iterator<T2> it2) {
this.it1 = it1; this.it2 = it2;
}
#Override
public boolean hasNext() { return it1.hasNext() && it2.hasNext(); }
#Override
public Pair<T1, T2> next() {
return new Pair<T1, T2>(it1.next(), it2.next());
}
#Override
public void remove(){
it1.remove();
it2.remove();
}
}
public class IterablePair <T1, T2> implements Iterable<Pair<T1,T2>> {
private final List<T1> first;
private final List<T2> second;
public IterablePair(List<T1> first, List<T2> second) {
this.first = first;
this.second = second;
}
#Override
public Iterator<Pair<T1, T2>> iterator(){
return new ParallelIterator<T1,T2>( first.iterator(), second.iterator() );
}
}
void someFunction(){
IterablePair<X,Y> listPair = new IterablePair<X,Y>( x, y );
for( Pair<X,Y> pair : listPair ){
X x = pair.first();
...
}
}
This stops as soon as either list is out of elements, so you might want to check lists have equal size before creating an IterablePair.
Also, I can't make a new class to combine MobileSuit and Pilot.
That doesn't sound correct. It sounds like you can't replace MobileSuit and Pilot by a single class, but I don't see any reason why you can't have a single class that combines them - i.e. one which just has a getPilot() method and a getMobileSuit() method. You could use a generic Pair class for the same purpose, but a custom class would be easier to use.
On the other hand, if you want to do this sort of "zipping" operation in multiple places, it might be one solution. Alternatively, you could write a generic interface to represent the act of combining the two distinct items - which could return a SuitedPilot or whatever your combination class is.
The reason is that there might be Mobile Suits that have no pilots, and I'm not sure how to fix that by keeping them at the same class.
You can use null values, right? Which is the correct way of doing it - have each suit keep track of its pilot. If it has no pilot, then indicate that with a null value there.
But, if you're dead set on not doing that for some reason...
public class SuitAndPilot
{
public MobileSuit suit;
public Pilot pilot;
public SuitAndPilot(Suit s, Pilot p) {
suit = s;
pilot = p;
}
}
Why not have a class MannedMobileSuit as a subclass of MobileSuit that contains an instance of a pilot ? That would solve your problem by having a getPilot method.
Usually when you get such problems (needing to return two instances) it is because your Object model is not appropriate and should be changed. Keep your options open
Came across this page trying to solve this issue, and turns out that there's a library out there that's already solved it using Java 8 streams (check out the Zip function).
You can convert a list to a stream just by calling list.stream()
https://github.com/poetix/protonpack
Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB = Stream.of("Apple", "Banana", "Carrot", "Doughnut");
List<String> zipped = StreamUtils.zip(streamA,
streamB,
(a, b) -> a + " is for " + b)
.collect(Collectors.toList());
assertThat(zipped,
contains("A is for Apple", "B is for Banana", "C is for Carrot"));
Basically, assume MobileSuit and Pilot need to be separated.
That's fine, but here you're trying to treat them as a unit, so structure your code that way. The suggestions above use a Pair class or Map.Entry, but it's much better to provide a clearly-named object that represents a MobileSuit with a Pilot, e.g.:
public class OccupiedSuit {
private final MobileSuit suit;
private final Pilot pilot;
public OccupiedSuit(MobileSuit suit, Pilot pilot) {
this.suit = checkNotNull(suit);
this.pilot = checkNotNull(pilot);
}
// getters, equals, hashCode, toString
// or just use #AutoValue: https://github.com/google/auto/tree/master/value
}
Then, rather than constructing a custom Iterator/Iterable, just write a helper function that zips up the two lists. For example:
public static List<OccupiedSuit> assignPilots(
Iterable<MobileSuit> suits, Iterable<Pilot> pilots) {
Iterator<MobileSuit> suitsIter = suits.iterator();
Iterator<Pilot> pilotsIter = pilots.iterator();
ImmutableList.Builder<OccupiedSuit> builder = ImmutableList.builder();
while (suitsIter.hasNext() && pilotsIter.hasNext()) {
builder.add(new OccupiedSuit(suitsIter.next(), pilotsIter.next()));
}
// Most of the existing solutions fail to enforce that the lists are the same
// size. That is a *classic* source of bugs. Always enforce your invariants!
checkArgument(!suitsIter.hasNext(),
"Unexpected extra suits: %s", ImmutableList.copyOf(suitsIter));
checkArgument(!pilotsIter.hasNext(),
"Unexpected extra pilots: %s", ImmutableList.copyOf(pilotsIter));
return builder.build();
}
Now you don't need to maintain a complex custom Iterator implementation - just rely on one that already exists!
We can also generalize assignPilots() into a generic utility that works for any two inputs, like so:
public static <L,R,M> List<M> zipLists(
BiFunction<L,R,M> factory, Iterable<L> left, Iterable<R> right) {
Iterator<L> lIter = left.iterator();
Iterator<R> rIter = right.iterator();
ImmutableList.Builder<M> builder = ImmutableList.builder();
while (lIter.hasNext() && rIter.hasNext()) {
builder.add(factory.apply(lIter.next(), rIter.next()));
}
checkArgument(!lIter.hasNext(),
"Unexpected extra left elements: %s", ImmutableList.copyOf(lIter));
checkArgument(!rIter.hasNext(),
"Unexpected extra right elements: %s", ImmutableList.copyOf(rIter));
return builder.build();
}
Which you'd then invoke like so:
List<OccupiedSuit> occupiedSuits = zipLists(OccupiedSuit::new, suits, pilots);
Example code uses Guava's Preconditions and ImmutableList - if you don't use Guava it's easy enough to inline and swap to ArrayList, but just use Guava :)
for(int i=0; i < mobileSuits.size(); i++) {
MobileSuit suit = mobileSuits.get(i);
Pilot pilot = pilots.get(i);
...
}
You could just use a Map<MobileSuit, Pilot>, where a null value mapped to a MobileSuit indicates no pilot. The Iterator could just be an Iterator<Map.Entry<MobileSuit, Pilot>> retrieved by map.entrySet().iterator().
Improving on the answer by user2224844, here is a simple version that will try no to run into an exception:
final Iterator<String> pilotIterator = pilots.iterator();
mobileSuits.forEach(m -> {
Pilot p = pilotIterator.hasNext()? pilotIterator.next():nullOrWahtever;
<Now do your work with m and p variables>
...
});
Isn't that enough ?
for(MobileSuit ms : MobileSuits) {
for(Pilot p : pilots){
//TODO
}
}

Is there a basic Java Set implementation that does not permit nulls?

The API for the Java Set interface states:
For example, some implementations prohibit null elements and some have restrictions on the types of their elements
I am looking for a basic Set implementation that does not require ordering (as ArrayList provides for the List interface) and that does not permit null. TreeSet, HashSet, and LinkedHashSet all allow null elements. Additionally, TreeSet has the requirement that elements implement Comparable.
It seems that no such basic Set exists currently. Does anyone know why? Or if one does exist where I can find it?
[Edit]: I do not want to allow nulls, because later in the code my class will iterate over all elements in the collection and call a specific method. (I'm actually using HashSet<MyRandomObject>). I would rather fail fast than fail later or accidentally incur some bizarre behavior due to a null being in the set.
Better than extending a particular implementation, you can easily write a proxy implementation of Set that checks for nulls. This analogous to Collections.checkedSet. Other than being applicable to any implementation, you can also be sure that you have overridden all applicable methods. Many flaws have been found by extending concrete collections which then have additional methods added in later versions.
I would say use composition instead of inheritance... it might be more work but it'll be more stable in the face of any changes that Sun might make to the Collections Framework.
public class NoNullSet<E> implements Set<E>
{
/** The set that is wrapped. */
final private Set<E> wrappedSet = new HashSet<E>();
public boolean add(E e)
{
if (e == null)
throw new IllegalArgumentException("You cannot add null to a NoNullSet");
return wrappedSet.add(e);
}
public boolean addAll(Collection<? extends E> c)
{
for (E e : c) add(e);
}
public void clear()
{ wrappedSet.clear(); }
public boolean contains(Object o)
{ return wrappedSet.contains(o); }
... wrap the rest of them ...
}
Note that this implementation does not depend on addAll calling add (which is an implementation detail and should not be used because it cannot be guaranteed to remain true in all Java releases).
There is no basic proprietary Set implementation that ignores or constrains null! There is EnumSet, but that one is tailors for the containment of enum types.
However, creating your own implementation can be avoided, if you use either Guava or Commons Collections:
1. Guava Solution:
Set noNulls = Constraints.constrainedSet(new HashSet(), Constraints.notNull());
2. Commons Collections:
Set noNulls = new HashSet();
CollectionUtils.addIgnoreNull(noNulls, object);
You could use apache collections and its PredicatedCollection class, and set the predicate to not allow nulls. You will get exceptions if someone sends nulls in.
This is a failry general purpose way of doing it - you provide a Filter implementation that can restrict what gets added in whatevber way you want. Take a look at the source for java.util.Collections for ideas on the wrapping (I think my implementaiton of the FilteredCollection class is correct... but it is not extensivly tested). There is a sample program at the end that shows the usage.
public interface Filter<T>
{
boolean accept(T item);
}
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
public class FilteredCollections
{
private FilteredCollections()
{
}
public static <T> Collection<T> filteredCollection(final Collection<T> c,
final Filter<T> filter)
{
return (new FilteredCollection<T>(c, filter));
}
private static class FilteredCollection<E>
implements Collection<E>,
Serializable
{
private final Collection<E> wrapped;
private final Filter<E> filter;
FilteredCollection(final Collection<E> collection, final Filter<E> f)
{
if(collection == null)
{
throw new IllegalArgumentException("collection cannot be null");
}
if(f == null)
{
throw new IllegalArgumentException("f cannot be null");
}
wrapped = collection;
filter = f;
}
public int size()
{
return (wrapped.size());
}
public boolean isEmpty()
{
return (wrapped.isEmpty());
}
public boolean contains(final Object o)
{
return (wrapped.contains(o));
}
public Iterator<E> iterator()
{
return new Iterator<E>()
{
final Iterator<? extends E> i = wrapped.iterator();
public boolean hasNext()
{
return (i.hasNext());
}
public E next()
{
return (i.next());
}
public void remove()
{
i.remove();
}
};
}
public Object[] toArray()
{
return (wrapped.toArray());
}
public <T> T[] toArray(final T[] a)
{
return (wrapped.toArray(a));
}
public boolean add(final E e)
{
final boolean ret;
if(filter.accept(e))
{
ret = wrapped.add(e);
}
else
{
// you could throw an exception instead if you want -
// IllegalArgumentException is what I would suggest
ret = false;
}
return (ret);
}
public boolean remove(final Object o)
{
return (wrapped.remove(o));
}
public boolean containsAll(final Collection<?> c)
{
return (wrapped.containsAll(c));
}
public boolean addAll(final Collection<? extends E> c)
{
final E[] a;
boolean result;
a = (E[])wrapped.toArray();
result = false;
for(final E e : a)
{
result |= wrapped.add(e);
}
return result;
}
public boolean removeAll(final Collection<?> c)
{
return (wrapped.removeAll(c));
}
public boolean retainAll(final Collection<?> c)
{
return (wrapped.retainAll(c));
}
public void clear()
{
wrapped.clear();
}
public String toString()
{
return (wrapped.toString());
}
}
}
import java.util.ArrayList;
import java.util.Collection;
public class Main
{
private static class NullFilter<T>
implements Filter<T>
{
public boolean accept(final T item)
{
return (item != null);
}
}
public static void main(final String[] argv)
{
final Collection<String> strings;
strings = FilteredCollections.filteredCollection(new ArrayList<String>(),
new NullFilter<String>());
strings.add("hello");
strings.add(null);
strings.add("world");
if(strings.size() != 2)
{
System.err.println("ERROR: strings.size() == " + strings.size());
}
System.out.println(strings);
}
}
Yes -- in the docs for com.google.common.collect.ImmutableSet:
A high-performance, immutable Set with reliable, user-specified iteration order. Does not permit null elements.
You could easily write your own, by subclassing an appropriate existing class, and overriding all relevant methods so that you can't add null elements.
You may also wish to check out Google Collections. They are more null phobic, I believe.
for me, I didn't find one,
so I overrode the add function
Collection<String> errors = new HashSet<String>() {
#Override
public boolean add(String s) {
return StringUtil.hasContent(s) && super.add(s);//we don't want add null and we allow HashSet.add(null)
}
};
[Edit]: I do not want to allow nulls, because later in the code my
class will iterate over all elements in the collection and call a
specific method.
Instead of checking null, every time, we can simply remove the null once before iterating over the set.
You can remove the null values using set.remove(null);
Set<String> set = new HashSet<>();
set.add("test");
set.add(null);
set.add(null);
System.out.println(set);
set.remove(null);
System.out.println(set);
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
Output
[null, test]
[test]
test
BTW, if you'd asked for a Map implementation that does not allow nulls, the old java.util.Hashtable does not.
In this particular question/example surely if you have a HashSet<MyRandomObject> mySet call mySet.remove(null) before starting the iteration over all elements you mentioned?
I am not sure of a type which this is true. But could you not inherit from a collection or HashTable of your choice and override the Add method, throwing an exception if the element is null?
Why do you not want to allow null?
Do you want to throw an exception if null is added to your set? If so, just do something like this:
private Set<Object> mySet = new HashSet<Object>() {
#Override
public boolean add(Object e) {
if (e == null)
throw new IllegalArgumentException("null"); // or NPE
// or, of course, you could just return false
return super.add(e);
}
};
HashSet's addAll() calls add() repeatedly, so this is the only method you'd have to override.
Hashtable does not allow null values......

Categories

Resources