Reputation: 23
I want convert a List to a Map
public Map<Integer, A> toMap(List<A> list) {
Map<Integer, A> map = new HashMap<>();
int sum = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getKey() != 0) {
sum += Math.abs(list.get(i).getKey());
map.put(sum, list.get(i));
}
}
return map;
}
How to express that with lambda?
Upvotes: 2
Views: 131
Reputation: 30676
Maybe using foreach
will be more effectively. Not have to be convert everything to a stream when it violate KISS , for
, foreach
,while
loop is not dead. I will giving the stream code later which is a bit more big.
public Map<Integer, A> toMap(List<A> list) {
Map<Integer, A> map = new HashMap<>();
int prevKey = 0;
for (A item : list) {
int key = item.getKey();
if (key != 0) {
map.put(prevKey += Math.abs(key), item);
}
}
return map;
}
or you maybe need combine foreach
& Stream
to describe that doing two things filtering
& mapping
.
public Map<Integer, A> toMap(List<A> list) {
Map<Integer, A> map = new HashMap<>();
int prevKey = 0;
for (A item : each(list.stream().filter(it -> it.getKey() != 0))) {
map.put(prevKey += Math.abs(item.getKey()), item);
}
return map;
}
private static <T> Iterable<? extends T> each(Stream<T> stream) {
return stream::iterator;
}
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.function.Function.identity;
public Map<Integer, A> toMap(List<A> list) {
AtomicInteger prevKey = new AtomicInteger(0);
return list.stream().filter(it -> it.getKey() != 0)
.collect(Collectors.toMap(curry(prevKey::addAndGet, A::getKey)
,identity()));
}
// e.g: AtomicInteger.addAndGet(A.getKey())
<T, U, R> Function<T, R> curry(Function<U, R> target, Function<T, U> mapper) {
return (it) -> target.apply(mapper.apply(it));
}
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.stream.Collectors;
import java.util.Map;
public Map<Integer, A> toMap(List<A> list) {
return list.stream().filter(it -> it.getKey() != 0).
collect(Stack::new, this::calculateKey, Stack::addAll).stream().
collect(Collectors.toMap(Entry::getKey, Entry::getValue));
}
private void calculateKey(Stack<Entry<Integer, A>> stack, A a) {
Integer prevKey = stack.isEmpty() ? 0 : stack.peek().getKey();
Integer key = prevKey + a.getKey();
stack.push(new SimpleEntry<>(key, a));
}
Upvotes: 2
Reputation: 43078
Something like this:
List<Integer> mList = Arrays.asList(1,2,3,4,5,2,-1,3,0,1);
Map<Integer, Integer> map = mList.stream()
.filter(i -> i != 0)
.collect(Collectors.toMap(new Function<Integer, Integer>() {
int sum = 0;
@Override
public Integer apply(Integer integer) {
sum += integer;
return sum;
}
}, Function.identity()));
I've done it for List<Integer>
, now you should do the same for List<A>
.
Integer
with A
.Upvotes: 0