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.
Related
To preface this, I've looked for numerous examples prior to asking and can't find any solution in regards to my problem.
I'm trying to implement a generic queue in a program I'm making, but stuck at a certain point. The program I've made is supposed to simulate a printer, queued with print jobs. There is a Queue class, PrintQueue class, and job class. (It is important to note the Job class consists of a job ID and String of who ordered it). I've included a function (in the printQueue class) where if the first job matches the job ID you put in, it will be deleted.
Unfortunately however, the queue is generic. This means I can't traverse the array with just an integer to check equality because it is a queue of job objects. To fix this I create a job with a blank name, and regular ID. The Job class has an equals method, which determines if either ID or Owner match, then it is true. But when I execute the code, this class is not called. The generic equals class is called instead, which will of course be false. After looking at many examples on this site, I tried all the recommended solutions, which did not work for me as my case (and problem) are different. What can I do to override the generic equals method? My code below is as simple as I could make it to reproduce this problem while keep context.
JOB CLASS
public class Job{
private String owner;
private int jobId;
public Job(String o, int j){
owner = o;
jobId = j;
}
public String getOwner(){
return owner;
}
public int getJobId(){
return jobId;
}
public String toString() {
return owner + " " + jobId + ". ";
}
public boolean equals(Job a) {
if(this.jobId == a.getJobId() || this.owner.equals(a.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
}
GENERIC QUEUE CLASS
import java.util.ArrayList;
public class Queue<T>{
private ArrayList<T> queue;
public Queue() {
queue = new ArrayList<T>();
}
public void enQueue(T obj1) {
queue.add(obj1);
}
public T deQueue() {
if(queue.size() != 0) {
T temp = queue.get(queue.size() - 1);
queue.remove(queue.size() -1);
return temp;
}
else
return null;
}
public int size() {
return queue.size();
}
public boolean isEmpty() {
if (size() == 0) {
return true;
}
else
return false;
}
public int positionOf(T a) {
for(int x = 0; x < queue.size(); x++) {
if(a.equals(queue.get(x))) {
System.out.println("Positionmatch");
return x;
}
}
return -1;
}
}
PRINTQUEUE CLASS
public class PrintQueue {
Queue<Job> prqueue = new Queue<Job>();
public PrintQueue() {}
public void lprm(int jobID) { //Removes the active job at the front of the queue if jobId matches, error message otherwise
//I can't JUST use jobID to check the position because the queue is a collection of JOBS not JobId's
if (prqueue.positionOf(new Job("",jobID))==0) {
prqueue.deQueue();
}
else if (prqueue.positionOf(new Job("",jobID))== -1) {
System.out.println("Job does not occupy first row.");
}
}
}
I know this is an extensive question, so if you do take the time to read it thank you very much. I wouldn't ask this if I could find the answer anywhere else.
Solution is simple: you are not overriding equals in your class, common mistake. Always annotate your methods with #Override so you can avoid this mistake.
Real equals method is taking an Object parameter, and yours has a Job as parameter, change that to Object and then cast it accordingly.
If you are using IDE I suggest right click -> source -> generate equals and you will see a good example how to do it.
You have to override your methods like this
#Override
public boolean equals(Object a) {
if(!(a instanceof Job))
throw new IllegalArgumentException();
Job job =(Job)a;
if(this.jobId == job.getJobId() || this.owner.equals(job.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
See also Why do I need to override the equals and hashCode methods in 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. :-)
Okay so I have a batch of methods returning boolean values of true/false.
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
updateMainTabsAccess();
updateUserPaymentTabPermissions();
updateUserRegistrationTabPermissions();
updateUserStudentsTabPermissions();
updateUserFacultyTabPermissions();
updateUserHomePermissions(); //saves any update made on existing user settings/permissions
updateUserInformation(); // sasve any update made on existing user information such as username
}
I would like to know if it's possible for me to check each of the methods' return value through a for-each loop.
I'm thinking of creating a private boolean isUpdateSuccessful() method.
Say like,
private boolean isUpdateSuccessful(){
Boolean a = updateMainTabsAccess();
Boolean b = updateUserPaymentTabPermissions();
//........so on....
Boolean result = (a && b &&...)
return result;
}
Problem is, I don't know if it's possible to put them in an arraylist or component array like
ArrayList<Boolean> listOfMethods = new ArrayList<Boolean>(method1,method2..);
So that I can then check each through a for-each loop
for(Boolean b:listOfMethods){
Boolean successful=true;
successful = (successful && b)
}
My questions are:
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
I'd appreciate any answer or suggestion. I simply want to check if every method was successful. I thought of using ?1:0:
Thanks in advance.
If I am you, I would do this. Just a sample code:
private void saveChangesOnEditButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (updateMainTabsAccess()) {
if (updateUserPaymentTabPermissions()) {
if (updateUserRegistrationTabPermissions()) {
...
} else {
// error on update registration
}
} else {
// error on update payment
}
}
With the above style:
You don't execute other methods when the before one fails.
Can have detailed error messages for each error.
You need not to main a collection and iteration.
Why not use a Stream to check the results:
Stream.<Boolean>of(updateMainTabsAccess(),
updateUserPaymentTabPermissions(),
updateUserRegistrationTabPermissions(),
updateUserStudentsTabPermissions(),
updateUserFacultyTabPermissions(),
updateUserHomePermissions(),
updateUserInformation()).allMatch(b -> b);
this way you get rid of short circuit evaluation and also don't need to create method references for each method.
method references
List<Supplier<Boolean>> methods = Arrays.asList(this::updateMainTabsAccess,
this::updateUserPaymentTabPermissions,
...
);
for (Supplier<Boolean> supplier : methods) {
boolean methodResult = supplier.get();
...
}
This can hardly be considered an improvement though...
this will find all method in side your class which is return Boolean after automatically invoke method one by one and store response to successful variable
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class Test {
public static void main(String[] args) {
Test test = new Test();
Class c = test.getClass();
boolean successful = true;
for (Method method : c.getDeclaredMethods()) {
if (method.getReturnType().toString().equals("boolean")) {
try {
String mname = method.getName();
Object o = method.invoke(test, null);
System.out.format("%s() returned %b%n", mname, (Boolean) o);
successful = successful && (Boolean) o;
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println("final answer : " + successful);
}
public boolean a() {
return true;
}
public boolean b() {
return false;
}
public boolean c() {
return false;
}
}
Hope its help to you.
If you want every method to be executed and check if every method scucceded you could simply write
boolean success = updateMainTabsAccess() &
updateUserPaymentTabPermissions() &
updateUserRegistrationTabPermissions() &
updateUserStudentsTabPermissions() &
updateUserFacultyTabPermissions() &
updateUserHomePermissions() &
updateUserInformation();
You have already received some answers.
Fabian's is a good one if you are using java 8.
But to answer directly your points
1.) How do I extract the return values of these methods and use the methods to initialize the Arraylist.
ArrayList<Boolean> resultsList = new ArrayList<Boolean>();
resultsList.add(updateMainTabsAccess());
...
2.) Using for-each loop, is there any possibility of what I'm trying to do? I none, then what do you suggest I do?
boolean res = true;
for (Boolean singleResult : resultsList) {
res = res && singleResult;
}
Here is the old style way to acheive your goal when Lambdas weren't introduced by Java 8.
public class TestMethodsListCall {
public abstract class Checker {
public abstract boolean check();
}
public static void main(String[] args) {
new TestMethodsListCall();
}
public TestMethodsListCall() {
final TestMethodsListCall that = this;
List<Checker> checkers = Arrays.asList( //
new Checker() { public boolean check() { return that.methodA(); } }, //
new Checker() { public boolean check() { return that.methodB(); } } //
// , ...
);
boolean res = true;
for (Checker c : checkers) {
res = res & c.check();
if (!res) {
// Break, display some message or all together
}
}
}
public boolean methodA() {
return true;
}
public boolean methodB() {
return false;
}
}
I want to write a method that removes all elements from a collection that follow a certain pattern. In functional languages, I would use filter() with a lambda expression. However, in Java, it seems I'm stuck with this:
public void removeAllBlueCars() {
LinkedList<Car> carsToRemove = new LinkedList<Car>();
for (Car c : cars) {
if (c.getCarColor() == Color.BLUE) {
carsToRemove.add(c);
}
}
cars.removeAll(carsToRemove );
}
Removing elements directly causes a ConcurrentModificationException. Is there a better way to do this without resorting to Google Collections?
With Java 8, you can filter with a lambda expression using Collection.removeIf.
cars.removeIf(c -> c.getCarColor() == Color.BLUE);
Maybe you could use iterators, which are a little more efficient:
public void removeAllBlueCars() {
Iterator<Car> carsIterator = cars.iterator();
while (carsIterator.hasNext()) {
Car c = carsIterator.next();
if (c.getCarColor() == Color.BLUE) {
carsIterator.remove();
}
}
}
Also, if you want to make this solution more generic, I'd suggest you something like:
public interface Filter<T> {
public boolean shouldRemove(T t);
}
And you could use it like this:
public void removeCars(Filter<Car> filter) {
Iterator<Car> carsIterator = cars.iterator();
while (carsIterator.hasNext()) {
Car c = carsIterator.next();
if (filter.shouldRemove(c)) {
carsIterator.remove();
}
}
}
Your method gets called like this:
removeCars(new Filter<Car>() {
public boolean shouldRemove(Car car) {
return car.getCarColor() == Color.BLUE;
}
});
You could iterate through the list using a ListIterator, which has a remove method.
Btw you should declare your list as List<Car> - program for interfaces, not implementation.
You can use CollectionUtils.filter(). It works with an Iterator, so it should have no problems removing items directly from the Collection. It is another dependency though. If you want the code standalone it would be:
public interface Predicate {
boolean evaluate(Object o);
}
public static void filter(Collection collection, Predicate predicate) {
if ((collection != null) && (predicate != null))
for (Iterator it = collection.iterator(); it.hasNext(); )
if (!predicate.evaluate(it.next()))
it.remove();
}
...
filter(collection, new Predicate() {
public boolean evaluate(Object o) { return whatever; }
});
Here is the Android way to implement a generic solution for this:
Usage:
Remove all null strings from my list
LinkedList<String> list = ...
ListUtils.filter(list, new ListUtils.Filter<String>() {
#Override
public boolean keepItem(String item) {
return item != null;
}
});
Source:
public class ListUtils {
public interface Filter<T>{
boolean keepItem(T item);
}
public static <T> void filter(#NonNull List<T> items, #NonNull Filter<T> filter) {
for (Iterator<T> iterator = items.iterator(); iterator.hasNext();){
if(!filter.keepItem(iterator.next())){
iterator.remove();
}
}
}
}
See if lambdaj's filter option can help you.
You could always go backwards and delete the elements..
for (int i = array.size() - 1; i >= 0; i--) {
if (array.get(i).getCarColor() == Color.BLUE)
array.remove(i);
}
edit: Noticed it was a LinkedList which might make my answer a bit non-relevant.
I'm a big fan of the Iterator solution provided by Vivien Barousse and gpeche. But I wanted to point out that you don't have to actually remove any elements from the collection, you just need to prevent the filter from returning them. That way, you basically have multiple views of the same collection, which can be very convenient and efficient. The Filter object is basically your lamda expression, or as close as you're gonna get in Java until version 7...
It's really an old post but how abt using the way given in Oracle Java tutorial.
static void filter(Collection<?>c) {
for (Iterator<?>it = c.iterator(); it.hasNext(); )
if (!cond(it.next()))
it.remove();
}
public static <T> void filter(List<T> list, Predicate<? super T> removeIf) {
if(list == null) return;
Iterator<T> iterator = list.iterator();
while (iterator.hasNext()) {
if (removeIf.apply(iterator.next())) iterator.remove();
}
}
Pass a list of some generic type to this function with a predicate to remove unwanted elements.
With Java8 introducing lambda expressions, it's much easier to implement filtering on a collection in a more functional approach.
I wrote an example for you. Please also note how nicer it is to print Collection content using forEach:
public class Java8Filtering {
public static void main(String[] argc) {
LinkedList<Car> cars = new LinkedList<>();
cars.add(new Car("car 1", Color.BLUE));
cars.add(new Car("car 2", Color.GREEN));
cars.add(new Car("car 3", Color.RED));
cars.add(new Car("car 4", Color.BLUE));
List<Car> filteredCars = cars.stream()
.filter(car -> car.getCarColor() != Color.BLUE)
.collect(Collectors.toList());
filteredCars.forEach(car -> System.out.println("Car: " + car.getCarName() + " with color: " + car.getCarColor()));
}
}
class Car {
private Color carColor;
private String carName;
public Car(String carName, Color carColor) {
this.carName = carName;
this.carColor = carColor;
}
public Color getCarColor() {
return carColor;
}
public void setCarColor(Color carColor) {
this.carColor = carColor;
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
}
enum Color {
BLUE, GREEN, RED
}
For those of you who come across this thread and might be working on Android with RxJava/RxAndroid, there's a quick way to do this without adding the Apache Commons Collections dependency:
cars = Observable.from(cars).filter(car -> {
if (car.getCarColor() == Color.BLUE) {
return false;
}
return true;
}).toList().toBlocking().first();
Note that I also happen to be using lambda expressions with Retrolambda. If you aren't using Retrolambda, you can express the same thing using the following:
cars = Observable.from(cars).filter(new Func1<Car, Boolean>() {
#Override
public Boolean call(Car car) {
if (car.getCarColor() == Color.BLUE) {
return false;
}
return true;
}
}).toList().toBlocking().first();
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......