Considering I have the following class:
public class Problem2 extends Problem<Integer> {
#Override
public void run() {
result = toList(new FibSupplier(i -> (i <= 4_000_000)))
.stream()
.filter(i -> (i % 2 == 0))
.mapToInt(i -> i)
.sum();
}
#Override
public String getName() {
return "Problem 2";
}
private static <E> List<E> toList(final Iterator<E> iterator) {
List<E> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
private class FibSupplier implements Iterator<Integer> {
private final IntPredicate hasNextPredicate;
private int beforePrevious = 0;
private int previous = 1;
public FibSupplier(final IntPredicate hasNextPredicate) {
this.hasNextPredicate = hasNextPredicate;
}
#Override
public boolean hasNext() {
return hasNextPredicate.test(previous);
}
#Override
public Integer next() {
int result = beforePrevious + previous;
beforePrevious = previous;
previous = result;
return result;
}
}
}
If you take a look at FibSupplier you can see that it exposes a generalized problem, even though it has a specialized implementation here, what I've managed to extract are:
It has a Predicate.
It has initial variables.
It has a variable that needs to be tested by the predicate.
It has a custom next() method.
My attempt to generalize this was with the following, note that I use a generic version for now instead of a specialized integer version:
public class FiniteSupplier<E> implements Iterator<E> {
private final Predicate<E> predicate;
public FiniteSupplier(final Predicate<E> predicate) {
this.predicate = predicate;
}
#Override
public boolean hasNext() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public E next() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
I want to be able to call FiniteSupplier with a predicate, however now I do not really know how to implement the other requirements I have managed to extract. I understand it could be done by extending the FiniteSupplier and making it abstract, but is that the correct way to do it?
The method test(int/Integer) can be used as Predicate<Integer> and as IntPredicate. The compiler does the conversion:
IntPredicate ip = (i) -> i>0;
Predicate<Integer> pi = (i) -> i>0;
Predicate<Integer> ip2pi = ip::test;
IntPredicate pi2ip = pi::test;
But you can't cast the two types as they are not assignable. IntPredicate does not extend Predicate.
So just use ::test when you create FibSupplier:
new FibSupplier(p) => new FibSupplier(p::test)
Or do that in a constructor. I'd introduce a new abstract type FiniteIntSupplier with an extra constructor that takes an IntSupplier and converts it to a general Supplier:
public FiniteIntSupplier(IntPredicate p) {
this(p::test);
}
Related
I have some code like this:
public class A {
private final Map<String, Runnable> map = new HashMap<>();
public A() {
map.put("a", () -> a());
map.put("b", () -> b());
}
public int a() {
return 1;
}
public int b() {
return 2;
}
public int c(String s) {
// map.get(s).run(); <= returns void, but
// I need the result of the
// function paired to the string.
// What TODO?
}
}
I have not-void functions (a(), b()) as values of a map, paired to Strings. I need to run the functions and get the result of the functions, and return it in the function c(). The run() function returns void, so I can't get the value from it. Is there any way to do this?
What you want to do here is to return an int value from the method. For that, you can't use a Runnable as run() doesn't return a value.
But you can use an IntSupplier, which is a functional interface representing a function supplying an int value. Its functional method getAsInt is used to return the value.
public class A {
private final Map<String, IntSupplier> map = new HashMap<>();
public A() {
map.put("a", () -> a()); // or use the method-reference this::a
map.put("b", () -> b()); // or use the method-reference this::b
}
public int a() {
return 1;
}
public int b() {
return 2;
}
public int c(String s) {
return map.get(s).getAsInt();
}
}
Additionally, if you don't want to return a primitive but an object MyObject, you can use the Supplier<MyObject> functional interface (or Callable<MyObject> if the method to call can throw a checked exception).
The fact that lambdas are new does not mean they are necessary for every (perhaps any) solution. Consider this tried-and-true java 5 feature (a little something called enumeration objects).
public class Enumery
{
private static enum Stuffs
{
a(1),
b(2);
Stuffs(final int value)
{
this.value = value;
}
public int kapow()
{
return value;
}
final int value;
}
public int thing(final String stuffsName)
{
final int returnValue;
final Stuffs theStuffs;
theStuffs = Stuffs.valueOf(stuffsName);
returnValue = theStuffs.kapow();
return returnValue;
}
}
I have implemented a SubListIterator which is a small utility Iterator for iterating over sublists of a given list.
Suppose I have a List containing 13500 elements and I want to split it into 7 sublists and use them.
#Test
public void shouldSplitTheGivenListIntoSmallerLists() {
List<Long> given = new ArrayList<Long>();
for (int count = 0; count < 13500; count++) {
given.add(Long.valueOf(count));
}
List<List<Long>> actualSubLists = new ArrayList<List<Long>>();
for (List<Long> subList : SubListIterator.subList(given, 2000)) { // Line got compilation error
actualSubLists.add(subList);
}
assertEquals(7, actualSubLists.size());
}
Everything works well if I implement the SubListIterator directly with List<Long>.
Then I wanted to extend my SubListIterator to work with every List regardless their generic type, so I went changing List<Long> to List<?> and get the compilation error:
Type mismatch: cannot convert from element type List<?> to List<Long>
I tried with List<T> and it doesn't work either.
My question is: Is there anyway to achieve my goal which is making the SubListIterator to work with every List, not just List<Long>?
Below is the SubListIterator:
public class SubListIterator implements Iterator<List<?>>, Iterable<List<?>> {
public static SubListIterator subList(List<?> given, int itemsEachSubList) {
return new SubListIterator(given, itemsEachSubList);
}
private final List<?> whole;
private final int elementsEachPart;
private int fromIndex;
private int toIndex;
public SubListIterator(List<?> whole, int itemsEach) {
this.whole = whole;
this.elementsEachPart = itemsEach;
this.fromIndex = 0;
this.toIndex = elementsEachPart;
}
#Override
public boolean hasNext() {
return fromIndex < toIndex;
}
#Override
public List<?> next() {
List<?> nextSubList = whole.subList(fromIndex, toIndex);
fromIndex = toIndex;
toIndex = Math.min(toIndex + elementsEachPart, whole.size());
return nextSubList;
}
#Override
public void remove() {
throw new UnsupportedOperationException("This method is not supported");
}
#Override
public Iterator<List<?>> iterator() {
return this;
}
}
Thanks for your support
You need to generalize your SubListIterator.
public class SubListIterator<T> implements Iterator<List<T>>, Iterable<List<T>> {
public static <C> SubListIterator<C> subList(List<C> given, int itemsEachSubList) {
return new SubListIterator<C>(given, itemsEachSubList);
}
private final List<T> whole;
private final int elementsEachPart;
private int fromIndex;
private int toIndex;
public SubListIterator(List<T> whole, int itemsEach) {
this.whole = whole;
this.elementsEachPart = itemsEach;
this.fromIndex = 0;
this.toIndex = elementsEachPart;
}
#Override
public boolean hasNext() {
return fromIndex < toIndex;
}
#Override
public List<T> next() {
List<T> nextSubList = whole.subList(fromIndex, toIndex);
fromIndex = toIndex;
toIndex = Math.min(toIndex + elementsEachPart, whole.size());
return nextSubList;
}
#Override
public void remove() {
throw new UnsupportedOperationException("This method is not supported");
}
#Override
public Iterator<List<T>> iterator() {
return this;
}
}
I just started playing around Java 8 and Lambda Expression and I am curious if I can stop the Stream generation from inside the Lambda expession by returning a specific value
(like null). Is this possible with Stream.generate()?
private int counter;
private void generate()
{
System.out.println(Stream.generate(() -> {
if (counter < 10) {
counter++;
return RandomUtils.nextInt(100);
} else {
return null;
}
}).count());
}
Unfortunately this code does not terminate, so by simply returning null will not step out of the stream.
Java 9 and later includes this method:
Stream<T> takeWhile(Predicate<? super T> predicate);
to limit a stream by condition. So the workaround beneath is not needed anymore.
Original answer (for Java versions earlier than 9):
With Stream.generate this is per definition not possible from a lambda closure. It is by definition endless. Using limit() you are able make your stream fix sized. But this will not help you for conditions like:
if random>10 then stop
There is a possibility to limit a potential endless stream by condition. This is usefull if one does not know the size. Your friend here is a Spliterator and your sample code would look like:
System.out.println( StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<Integer>() {
int counter = 0;
#Override
public boolean hasNext() {
return counter < 10;
}
#Override
public Integer next() {
counter++;
return RandomUtils.nextInt(100);
}
}, Spliterator.IMMUTABLE), false).count());
Basically you are able to build a Stream from an Iterator. I am using this construct e.g. for a stream of XMLEvents from Stax XML - parsing.
I know this is not done by lambda constructs but it IHMO solves this lacking feature of stopping the stream item generation by condition.
I would be very interested, if there is a better way to achieve this (I mean this stream construct and not the XML processing ;)) or if there is a fundamental flaw in using streams in this way.
This is not possible with Lamdas, you cannot control the flow from inside the expression.
Even the API docs says that the Stream.generate generates an infinite stream.
However, you can limit the Stream and achieve the desired functionality simply by using the limit() method:
System.out.println(Stream.generate(() -> RandomUtils.nextInt(100)).limit(10).count());
// If you are not looking for parallelism, you can use following method:
public static <T> Stream<T> breakStream(Stream<T> stream, Predicate<T> terminate) {
final Iterator<T> original = stream.iterator();
Iterable<T> iter = () -> new Iterator<T>() {
T t;
boolean hasValue = false;
#Override
public boolean hasNext() {
if (!original.hasNext()) {
return false;
}
t = original.next();
hasValue = true;
if (terminate.test(t)) {
return false;
}
return true;
}
#Override
public T next() {
if (hasValue) {
hasValue = false;
return t;
}
return t;
}
};
return StreamSupport.stream(iter.spliterator(), false);
}
Use StreamSupport.stream(Spliterator, boolean)
See JavaDoc on Spliterator.
Here is example spliterator:
public class GeneratingSpliterator<T> implements Spliterator<T>
{
private Supplier<T> supplier;
private Predicate<T> predicate;
public GeneratingSpliterator(final Supplier<T> newSupplier, final Predicate<T> newPredicate)
{
supplier = newSupplier;
predicate = newPredicate;
}
#Override
public int characteristics()
{
return 0;
}
#Override
public long estimateSize()
{
return Long.MAX_VALUE;
}
#Override
public boolean tryAdvance(final Consumer<? super T> action)
{
T newObject = supplier.get();
boolean ret = predicate.test(newObject);
if(ret) action.accept(newObject);
return ret;
}
#Override
public Spliterator<T> trySplit()
{
return null;
}
}
This is another solution for java 8 (It needs a Stream.Builder, may be it is not optimal, but it is quite simple):
#SuppressWarnings("ResultOfMethodCallIgnored")
public static <T> Stream<T> streamBreakable(Stream<T> stream, Predicate<T> stopCondition) {
Stream.Builder<T> builder = Stream.builder();
stream.map(t -> {
boolean stop = stopCondition.test(t);
if (!stop) {
builder.add(t);
}
return stop;
})
.filter(result -> result)
.findFirst();
return builder.build();
}
And the test:
#Test
public void shouldStop() {
AtomicInteger count = new AtomicInteger(0);
Stream<Integer> stream = Stream.generate(() -> {
if (count.getAndIncrement() < 10) {
return (int) (Math.random() * 100);
} else {
return null;
}
});
List<Integer> list = streamBreakable(stream, Objects::isNull)
.collect(Collectors.toList());
System.out.println(list);
}
It is possible, you just need to think outside the box.
The following idea is borrowed from Python, the language which introduced me to generator functions...
Just throw an instance of RuntimeException when you are done from within the Supplier<T> closure and catch-and-ignore it at the call site.
An example excerpt (note I have added a safety catch of Stream.limit(Long.MAX_VALUE) to cover the unexpected, though it should never be triggered):
static <T> Stream<T> read(String path, FieldSetMapper<T> fieldSetMapper) throws IOException {
ClassPathResource resource = new ClassPathResource(path);
DefaultLineMapper<T> lineMapper = new DefaultLineMapper<>();
lineMapper.setFieldSetMapper(fieldSetMapper);
lineMapper.setLineTokenizer(getTokenizer(resource));
return Stream.generate(new Supplier<T>() {
FlatFileItemReader<T> itemReader = new FlatFileItemReader<>();
int line = 1;
{
itemReader.setResource(resource);
itemReader.setLineMapper(lineMapper);
itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
itemReader.setLinesToSkip(1);
itemReader.open(new ExecutionContext());
}
#Override
public T get() {
T item = null;
++line;
try {
item = itemReader.read();
if (item == null) {
throw new StopIterationException();
}
} catch (StopIterationException ex) {
throw ex;
} catch (Exception ex) {
LOG.log(WARNING, ex,
() -> format("%s reading line %d of %s", ex.getClass().getSimpleName(), line, resource));
}
return item;
}
}).limit(Long.MAX_VALUE).filter(Objects::nonNull);
}
static class StopIterationException extends RuntimeException {}
public void init() {
if (repository.count() == 0) {
Level logLevel = INFO;
try {
read("providers.csv", fields -> new Provider(
fields.readString("code"),
fields.readString("name"),
LocalDate.parse(fields.readString("effectiveStart"), DateTimeFormatter.ISO_LOCAL_DATE),
LocalDate.parse(fields.readString("effectiveEnd"), DateTimeFormatter.ISO_LOCAL_DATE)
)).forEach(repository::save);
} catch (IOException e) {
logLevel = WARNING;
LOG.log(logLevel, "Initialization was interrupted");
} catch (StopIterationException ignored) {}
LOG.log(logLevel, "{} providers imported.", repository.count());
}
}
My solution was to generate a null when done and then apply a filter
Stream
.generate( o -> newObject() )
.filter( o -> o != null )
.forEach(...)
I have a function myFunction of Function<Integer, T>, and I want to construct an object mylist of size size, implementing List<T> (or maybe some kind of immutable list interface), backed by the function, in the sense that mylist.get(i) == myFunction.apply(i).
I can do this manually, but is there some (Guava) code which does the same?
Just use java.util.AbstractList:
new AbstractList<T>() {
public T get(int i) {
Preconditions.checkElementIndex(i, size);
return function.apply(i);
}
public int size() {
return size;
}
}
The result would not necessarily be immutable, since the function output could vary. In all likelihood, you could get rid of the Function entirely, and just write the implementation of the Function in your AbstractList implementation.
Perhaps instead of a list you should consider an Iterator<T>.
// Example simple Function that returns each element from the array.
static class Function<T> {
final T[] t;
Function(T[] t) {
this.t = t;
}
T apply (Integer i) {
return t[i];
}
}
static class FunctionIterator<T> implements Iterator<T> {
final Function<T> f;
Integer i;
Integer to;
Integer step;
FunctionIterator(Function<T> f, Integer from, Integer to) {
this.f = f;
if ( to > from ) {
step = 1;
i = from;
this.to = to;
} else {
step = -1;
i = to;
this.to = from;
}
}
#Override
public boolean hasNext() {
return i != to + step;
}
#Override
public T next() {
T next = f.apply(i);
i += step;
return next;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
}
This code offers an Iterator. You can make an Iterable from it quite easily. Here is an excellent and neat example of how to do it.
I have a list of hosts in an array which represnt the servers available to do a particular job. Currently I simply iterate thru the list looking and establish comms with a host to check its not busy. If not I will send a job to it. This approach tends to mean that the first host in the list tends to get hot constanly with the load not balanced properly with the rest of the available hosts.
in pseudocode ..
for (Host h : hosts) {
//checkstatus
if status == job accepted break;
}
I'd like to balance this load properly between the hosts i.e first time host one is used 2nd time the method is used host 2. Just wondering that the most elegant solution to this is ??
Thanks
W
Google collections has a utility method Iterators.cycle(Iterable<T> iterable) that does what you want.
You can create a new kind of Iterable that provides round-robin iteration:
public class RoundRobin<T> implements Iterable<T> {
private List<T> coll;
public RoundRobin(List<T> coll) { this.coll = coll; }
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
T res = coll.get(index);
index = (index + 1) % coll.size();
return res;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
You need to define your hosts as RoundRobin<Host>.
[FIXED based on Mirko's comment]
If the list is mutable and the cost of editing it is negligible compared to I/O with the hosts, you can just rotate it:
List<String> list = Arrays.asList("one", "two", "three");
Collections.rotate(list, -1);
System.out.println(list);
IMHO the standard Java API already provides an easy way to accomplish this, without resorting to external libraries or even the need to implement a custom Iterator. Simply use a Deque where you'd pull the first server, use or discard it, then append it back to the end of the Deque. Here's some sample code:
// Initialize the Deque. This might be at your class constructor.
Deque<Host> dq = new ArrayDeque<Host>();
dq.addAll(Arrays.asList(hosts));
void sendJob(Job myJob) {
boolean jobInProcess = false;
do {
Host host = dq.removeFirst(); // Remove the host from the top
if(!host.isBusy()) {
host.sendJob(myJob);
jobInProcess = true;
}
dq.addLast(host); // Put the host back at the end
}
while(!jobInProcess); // Might add another condition to prevent an infinite loop...
}
This is just a sample where you always ping hosts in round robin order in a loop that only ends when one of them is available and takes the job. You could tinker with it easily to go only around the queue once (use a counter with a max set to the queue's size) or a number of times beofre throwing an exception, or sleeping in between rounds to avoid banging the hosts when all are busy.
My RoundRobin implementation, based upon the implementation of https://stackoverflow.com/a/2041772/1268954
/**
*
* #author Mirko Schulze
*
* #param <T>
*/
public class RoundRobin<T> implements Iterable<T> {
private final List<T> coll;
public RoundRobin(final List<T> coll) {
this.coll = NullCheck.throwExceptionIfNull(coll, "collection is null");
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
this.index = this.index % RoundRobin.this.coll.size();
final T t = RoundRobin.this.coll.get(this.index);
this.index++;
return t;
}
#Override
public void remove() {
throw new IllegalArgumentException("remove not allowd");
}
};
}
}
And the Junit TestCase
/**
*
* #author Mirko Schulze
*
*/
#RunWith(JUnit4.class)
public class RoundRobinTest extends TestCase {
private List<Integer> getCollection() {
final List<Integer> retval = new Vector<Integer>();
retval.add(Integer.valueOf(1));
retval.add(Integer.valueOf(2));
retval.add(Integer.valueOf(3));
retval.add(Integer.valueOf(4));
retval.add(Integer.valueOf(5));
return retval;
}
#Test
public void testIteration() {
final List<Integer> l = this.getCollection();
final Integer frst = l.get(0);
final Integer scnd = l.get(1);
final Integer thrd = l.get(2);
final Integer frth = l.get(3);
final Integer last = l.get(4);
Assert.assertEquals("die Collection hat für diesen Test nicht die passende Größe!", 5, l.size());
final RoundRobin<Integer> rr = new RoundRobin<Integer>(l);
final Iterator<Integer> i = rr.iterator();
for (int collectionIterations = 0; collectionIterations < 4; collectionIterations++) {
final Integer i1 = i.next();
Assert.assertEquals("nicht das erste Element", frst, i1);
final Integer i2 = i.next();
Assert.assertEquals("nicht das zweite Element", scnd, i2);
final Integer i3 = i.next();
Assert.assertEquals("nicht das dritte Element", thrd, i3);
final Integer i4 = i.next();
Assert.assertEquals("nicht das vierte Element", frth, i4);
final Integer i5 = i.next();
Assert.assertEquals("nicht das letzte Element", last, i5);
}
}
}
The implementations provided are buggy and might fail in case of parallelism , the easiest way i did it was to use a circular linked list whose pointer is maintained by an atomic integer.
If you are creating an Iterator, best to create a defensive copy first and have the iterator work on that.
return new MyIterator(ImmutableList.<T>copyOf(list));
public class RoundRobinIterator<T> implements Serializable {
private static final long serialVersionUID = -2472203060894189676L;
//
private List<T> list;
private Iterator<T> it;
private AtomicInteger index = new AtomicInteger(0);
public RoundRobinIterator(List<T> list) throws NullPointerException {
super();
if (list==null) {
throw new NullPointerException("List is null");
}
this.list=Collections.unmodifiableList(list);
}
public RoundRobinIterator(Collection<T> values) {
this(new ArrayList<T>(values));
}
public RoundRobinIterator(Iterator<T> values) {
this(copyIterator(values));
}
public RoundRobinIterator(Enumeration<T> values) {
this(Collections.list(values));
}
private final List<T> getList() {
return list;
}
private final Iterator<T> getIt() {
return it;
}
public final int size() {
return list.size();
}
public final synchronized T getNext(Filter<T> filter) {
int start = index.get();
T t = getNext();
T result = null;
while ((result==null) && (start!=getIndex())) {
if (filter.accept(t)) {
result=t;
} else {
t = getNext();
}
}
return result;
}
public final synchronized T getNext() {
if (getIt()==null) {
if (getList().size()==0) {
index.set(0);
return null;
} else {
it = getList().iterator();
index.set(0);
return it.next();
}
} else if (it.hasNext()) {
index.incrementAndGet();
return it.next();
} else {
if (list.size()==0) {
index.set(0);
return null;
} else {
index.set(0);
it = list.iterator();
return it.next();
}
}
}
public final synchronized int getIndex() {
return index.get();
}
private static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext()) {
copy.add(iter.next());
}
return copy;
}
}
Where Filter is
public interface Filter<T> {
public boolean accept(T t);
}