Skip to content

Instantly share code, notes, and snippets.

@quelgar
Created September 27, 2013 07:24
Show Gist options
  • Save quelgar/6725210 to your computer and use it in GitHub Desktop.
Save quelgar/6725210 to your computer and use it in GitHub Desktop.
import java.util.*;
import java.util.stream.Stream;
/**
* Find the most frequently occurring item that occurs more than once.
* Idea from http://skipoleschris.blogspot.com.au/2010/11/functional-programming-challenge-most.html
*/
public final class Most {
private static final class Accum<T> {
public final Optional<T> winning;
public final Map<T, Integer> seen;
public Accum(final Optional<T> winning, final Map<T, Integer> seen) {
this.winning = winning;
this.seen = seen;
}
}
private static <T> Accum<T> most2(final Accum<T> ac, final T x) {
// Java standard library does not have an immutable Map, so cheat slightly
final Map<T, Integer> newSeen = new HashMap<T, Integer>(ac.seen);
newSeen.compute(x, (k, v) -> v == null ? 1 : v + 1);
final int winningCount = ac.winning.map(ac.seen::get).orElse(1);
final int count = newSeen.get(x);
final Optional<T> newWinning = count > winningCount ? Optional.of(x) : ac.winning;
return new Accum<T>(newWinning, newSeen);
}
public static <T> Optional<T> most(final Stream<T> xs) {
return xs.reduce(new Accum<T>(Optional.empty(), Collections.emptyMap()), Most::most2,
(ac1, ac2) -> {
// this isn't actually used unless the reduce is run in parallel
// more cheating, sigh
final Map<T, Integer> seen = new HashMap<T, Integer>(ac1.seen);
for (final Map.Entry<T, Integer> e : ac2.seen.entrySet()) {
seen.merge(e.getKey(), e.getValue(), Integer::sum);
}
final Optional<T> winning = Optional.empty(); // TODO
throw new RuntimeException();
// return new Accum<T>(winning, seen);
}).winning;
}
public static <T> String mostText(final Stream<T> xs) {
return most(xs).map(Object::toString).orElse("None");
}
public static void main(final String[] args) {
final Stream<String> test1 = Stream.of("a", "b", "c", "a", "b", "a");
final Stream<String> test2 = Stream.of("a", "b", "c");
final Stream<String> test3 = Stream.of("a", "b", "a", "b");
final Stream<String> test4 = Stream.of("b", "a", "b", "a");
final Stream<String> test5 = Stream.empty();
final Stream<Integer> test6 = Stream.of(1, 2, 3, 4, 2, 3, 3, 3, 2);
System.out.println(mostText(test1));
System.out.println(mostText(test2));
System.out.println(mostText(test3));
System.out.println(mostText(test4));
System.out.println(mostText(test5));
System.out.println(mostText(test6));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment