Skip to content

Instantly share code, notes, and snippets.

@bnorm
Created March 11, 2016 17:12
Show Gist options
  • Save bnorm/2eddc0e353509f1b61cf to your computer and use it in GitHub Desktop.
Save bnorm/2eddc0e353509f1b61cf to your computer and use it in GitHub Desktop.
Class for collecting strings and producing a grammatically correct sentence fragment
public class Grammar<T> {
private T last;
private int count;
private final StringJoiner joiner;
public Grammar() {
this.last = null;
this.count = 0;
this.joiner = new StringJoiner(", ");
}
public int getCount() {
return count;
}
public Grammar<T> merge(Grammar<T> other) {
if (count == 0) {
return other;
} else if (other.count == 0) {
return this;
}
synchronized (joiner) {
if (count > 1) {
joiner.add(Objects.toString(last));
}
if (other.count > 1) {
joiner.merge(other.joiner);
}
}
last = other.last;
count += other.count;
return this;
}
public void add(T other) {
synchronized (joiner) {
if (count == 0) {
joiner.add(Objects.toString(other));
} else if (count > 1) {
joiner.add(Objects.toString(last));
}
}
last = other;
count += 1;
}
public static <T> Collector<T, ?, Grammar<T>> collector() {
return Collector.of(Grammar::new,
Grammar::add,
(singleton, other) -> singleton.merge(other),
Collector.Characteristics.UNORDERED,
Collector.Characteristics.CONCURRENT);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(joiner.toString());
if (count > 2) {
builder.append(','); // Oxford comma
}
if (count > 1) {
builder.append(" and ").append(last);
}
return builder.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment