Skip to content

List Converter — Java source

Transform a list between separators (newline, comma, space, pipe, semicolon, tab) with trim, dedupe, sort, and empty-removal options. 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 Converter — split/trim/dedup/sort/join between separators — Java (17+) port of the list-converter tool.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

public final class ListConverter {

    private ListConverter() {}

    /** Options mirror the TS ListOptions; defaults are from=newline, to=comma. */
    public static final class Options {
        public String from = "newline", to = "comma";
        public boolean trim, removeEmpty, unique, sort, caseInsensitive;
    }

    /** Resolve a TS-style separator name to its glue; unknown names pass
     *  through as a literal separator (the TS resolveSep behavior). */
    static String resolveSep(String name) {
        return switch (name) {
            case "newline" -> "\n";
            case "comma" -> ",";
            case "space" -> " ";
            case "pipe" -> "|";
            case "semicolon" -> ";";
            case "tab" -> "\t";
            default -> name;
        };
    }

    /** Convert a list between separators: split -> (trim) -> (drop empties) ->
     *  (dedup, first occurrence wins) -> (stable sort) -> join. Mirrors the Go twin. */
    public static String convert(String input, Options o) {
        // Pattern.quote: separators are regex metachars ('|'); limit -1 keeps
        // trailing empties, matching Go's strings.Split exactly.
        String[] parts = input.split(Pattern.quote(resolveSep(o.from)), -1);
        List<String> items = new ArrayList<>(List.of(parts));
        String to = resolveSep(o.to);

        if (o.trim) items.replaceAll(String::trim);
        if (o.removeEmpty) items.removeIf(String::isEmpty);
        if (o.unique) {
            // Keyed by the optionally-lowercased value; putIfAbsent keeps the
            // first occurrence's casing, LinkedHashMap preserves order.
            LinkedHashMap<String, String> first = new LinkedHashMap<>();
            for (String s : items) {
                first.putIfAbsent(o.caseInsensitive ? s.toLowerCase(Locale.ROOT) : s, s);
            }
            items = new ArrayList<>(first.values());
        }
        if (o.sort) { // List.sort (TimSort) is stable; only the key lowercases
            Comparator<String> cmp = o.caseInsensitive
                    ? Comparator.comparing(s -> s.toLowerCase(Locale.ROOT))
                    : Comparator.naturalOrder();
            items.sort(cmp);
        }
        return String.join(to, items);
    }

    public static void main(String[] args) {
        // "b\n a \nB\na\n\nc" -> trim, drop empties, case-insensitive dedup+sort
        Options o = new Options();
        o.trim = o.removeEmpty = o.unique = o.sort = o.caseInsensitive = true;
        System.out.println(convert("b\n a \nB\na\n\nc", o)); // a,b,c
    }
}

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 →