List Set Operations — Java source
Compute the union, intersection, difference, or symmetric difference of two newline-separated lists. Deduped results with optional trim and case-insensitive matching. Runs entirely in your browser, with a shareable link.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// list-set-ops — union / intersection / difference / symmetric difference of
// two newline-separated lists. Java port (canonical TS:
// src/lib/list-set-ops.ts; Go twin: cli/list-set-ops). HashSet is the
// membership set; trim defaults on like the TS `trim !== false`. split with
// limit -1 keeps trailing empty lines so trim-then-drop matches the TS split.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public class ListSetOps {
public static final class SetOptions {
final boolean caseInsensitive;
final boolean trim; // the TS default (omitted -> trim on)
public SetOptions() { this(false, true); }
public SetOptions(boolean caseInsensitive) { this(caseInsensitive, true); }
SetOptions(boolean caseInsensitive, boolean trim) {
this.caseInsensitive = caseInsensitive;
this.trim = trim;
}
}
// Folded membership key: lowercase copy when case-insensitive, else the item.
static String key(String s, SetOptions o) {
return o.caseInsensitive ? s.toLowerCase(Locale.ROOT) : s;
}
// Split a newline list into a deduped list (first-seen casing kept).
static List<String> parseList(String input, SetOptions o) {
List<String> items = new ArrayList<>();
if (input.isEmpty()) return items; // empty input = no items
Set<String> seen = new HashSet<>();
for (String item : input.split("\n", -1)) {
if (o.trim) {
item = item.strip();
if (item.isEmpty()) continue;
}
if (seen.add(key(item, o))) items.add(item);
}
return items;
}
// Compute a set op over two lists; the result is "\n"-joined.
public static String setOps(String a, String b, String op, SetOptions o) {
List<String> listA = parseList(a, o), listB = parseList(b, o);
Set<String> keysA = new HashSet<>(), keysB = new HashSet<>();
for (String s : listA) keysA.add(key(s, o));
for (String s : listB) keysB.add(key(s, o));
List<String> out = new ArrayList<>();
switch (op) {
case "union" -> { // every unique item, a then b
Set<String> seen = new HashSet<>();
for (String s : listA) if (seen.add(key(s, o))) out.add(s);
for (String s : listB) if (seen.add(key(s, o))) out.add(s);
}
case "intersect" -> { // items present in both (a's order/casing)
for (String s : listA) if (keysB.contains(key(s, o))) out.add(s);
}
case "difference" -> { // items in a not present in b
for (String s : listA) if (!keysB.contains(key(s, o))) out.add(s);
}
case "symmetricDifference" -> { // exactly one list, a-only then b-only
for (String s : listA) if (!keysB.contains(key(s, o))) out.add(s);
for (String s : listB) if (!keysA.contains(key(s, o))) out.add(s);
}
default -> {} // unknown op -> ""
}
return String.join("\n", out);
}
public static void main(String[] args) {
String A = "apple\nbanana\ncherry", B = "banana\ncherry\ndate";
System.out.println(setOps(A, B, "union", new SetOptions())); // apple\nbanana\ncherry\ndate
System.out.println(setOps(A, B, "intersect", new SetOptions())); // banana\ncherry
System.out.println(setOps(A, B, "difference", new SetOptions())); // apple
System.out.println(setOps(A, B, "symmetricDifference", new SetOptions())); // apple\ndate
// case-folded compare, first-seen original casing emitted
System.out.println(setOps("HELLO", "hello", "intersect", new SetOptions(true))); // HELLO
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →