diff --git a/src/main/java/net/xyzsd/dichotomy/collectors/EitherCollectors.java b/src/main/java/net/xyzsd/dichotomy/collectors/EitherCollectors.java
index c0724eb..98bc149 100644
--- a/src/main/java/net/xyzsd/dichotomy/collectors/EitherCollectors.java
+++ b/src/main/java/net/xyzsd/dichotomy/collectors/EitherCollectors.java
@@ -2,57 +2,115 @@
 
 import net.xyzsd.dichotomy.Conversion;
 import net.xyzsd.dichotomy.Either;
-import net.xyzsd.dichotomy.Result;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collector;
 
-
+/**
+ * Collectors for {@link Either}s.
+ * <p>
+ * Three collectors are provided. The default collector ({@link #collector()}
+ * is left-biased. However, both right-biased and a collector which will return
+ * all left and right values encountered are included.
+ * </p>
+ * <p>
+ * A left-biased collector will only return {@link net.xyzsd.dichotomy.Either.Right} values
+ * if no {@link net.xyzsd.dichotomy.Either.Left} values have been encountered, and at least
+ * one Right value was found. Otherwise,
+ * all encountered {@link net.xyzsd.dichotomy.Either.Left} values will be returned.
+ * </p>
+ */
 public interface EitherCollectors {
 
 
+    /**
+     * A left-biased collector of Eithers.
+     * <p>
+     *     This will return right values iff there are no left values, and
+     *     at least one right value is present.
+     * </p>
+     * @return An Either containing a List of Left or Right values, as above.
+     * @param <L> Left type
+     * @param <R> Right type
+     */
     static <L, R> Collector<Either<L, R>, ?, Either<List<L>, List<R>>> collector() {
         return Collector.<Either<L, R>, Accumulator<R, L>, Either<List<L>, List<R>>>of(
                 Accumulator::new,
                 EitherCollectors::add,
                 Accumulator::append,
-                    accum -> Conversion.toEither(accum.finishBiasErr())
+                accum -> Conversion.toEither( accum.finishBiasErr() )
         );
     }
 
+    /**
+     * A right-biased collector of Eithers.
+     * <p>
+     *     This will return Left values iff there are no right values
+     *     and at least a single left value is present.
+     * </p>
+     * @return An Either containing a List of Left or Right values, as above.
+     * @param <L> Left type
+     * @param <R> Right type
+     */
     static <L, R> Collector<Either<L, R>, ?, Either<List<L>, List<R>>> rightBiasedCollector() {
         return Collector.<Either<L, R>, Accumulator<R, L>, Either<List<L>, List<R>>>of(
                 Accumulator::new,
                 EitherCollectors::add,
                 Accumulator::append,
-                accum -> Conversion.toEither(accum.finishBiasOK())
+                accum -> Conversion.toEither( accum.finishBiasOK() )
         );
     }
 
-    static <L, R> Collector<Either<L, R>, ?, Both<L, R>> both() {
-        return Collector.<Either<L, R>, Accumulator<R, L>, Both<L, R>>of(
+    /**
+     * An unbiased collector of Eithers.
+     * <p>
+     *     This will return <b>both</b> Left and Right values
+     * </p>
+     * @return a tuple containing both Left and Right values.
+     * @param <L> Left type
+     * @param <R> Right type
+     */
+    static <L, R> Collector<Either<L, R>, ?, LeftsAndRights<L, R>> both() {
+        return Collector.<Either<L, R>, Accumulator<R, L>, LeftsAndRights<L, R>>of(
                 Accumulator::new,
                 EitherCollectors::add,
                 Accumulator::append,
-                accum -> new Both<>( accum.errList, accum.okList )
+                accum -> new LeftsAndRights<>( accum.errList, accum.okList )
         );
     }
 
-    static private <L,R> void add(Accumulator<R,L> listBox, Either<L,R> either) {
+
+    static private <L, R> void add(Accumulator<R, L> listBox, Either<L, R> either) {
         switch (either) {
             case Either.Left<L, R> left -> listBox.errList.add( left.value() );
             case Either.Right<L, R> right -> listBox.okList.add( right.value() );
         }
     }
 
-    record Both<ERR, OK>(List<ERR> errs, List<OK> oks) {
+    /**
+     * Tuple containing lists of Left and Right values
+     * <p>
+     *     Contained lists are immutable and never null, but may be empty.
+     * </p>
+     * @param lefts Left values
+     * @param rights Right values
+     * @param <L> Left type
+     * @param <R> Right type
+     */
+    record LeftsAndRights<L, R>(@NotNull List<L> lefts, @NotNull List<R> rights) {
 
-        public Both {
-            Objects.requireNonNull( oks );
-            Objects.requireNonNull( errs );
-            oks = List.copyOf( oks );
-            errs = List.copyOf( errs);
+        /**
+         * Create a LeftAndRights
+         * @param lefts left values
+         * @param rights right values
+         */
+        public LeftsAndRights {
+            Objects.requireNonNull( lefts );
+            Objects.requireNonNull( rights );
+            lefts = List.copyOf( lefts );
+            rights = List.copyOf( rights );
         }
 
     }
diff --git a/src/main/java/net/xyzsd/dichotomy/collectors/ResultCollectors.java b/src/main/java/net/xyzsd/dichotomy/collectors/ResultCollectors.java
index 7705d8f..1fe957d 100644
--- a/src/main/java/net/xyzsd/dichotomy/collectors/ResultCollectors.java
+++ b/src/main/java/net/xyzsd/dichotomy/collectors/ResultCollectors.java
@@ -2,16 +2,37 @@
 
 
 import net.xyzsd.dichotomy.Result;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
-import java.util.Objects;
 import java.util.stream.Collector;
 
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Collectors for {@link Result}s.
+ * <p>
+ * Three collectors are provided. The default collector ({@link #collector()}
+ * is error-biased. However, both ok-biased and a collector which will return
+ * all ok and error values encountered are included.
+ * </p>
+ */
 public interface ResultCollectors {
 
 
+    /**
+     * Default error-biased collector.
+     * <p>
+     * This will return Err values, unless there are none; then OK values will be returned.
+     * If there are no OK values (and no Err values), an Err with an empty List will be returned.
+     * </p>
+     *
+     * @param <OK>  OK type
+     * @param <ERR> Err type
+     * @return A Result containing a List of OK or Err values as described above.
+     */
     static <OK, ERR> Collector<Result<OK, ERR>, ?, Result<List<OK>, List<ERR>>> collector() {
-        return Collector.<Result<OK, ERR>, Accumulator<OK,ERR>, Result<List<OK>, List<ERR>>>of(
+        return Collector.<Result<OK, ERR>, Accumulator<OK, ERR>, Result<List<OK>, List<ERR>>>of(
                 Accumulator::new,
                 ResultCollectors::add,
                 Accumulator::append,
@@ -19,8 +40,19 @@ public interface ResultCollectors {
         );
     }
 
+    /**
+     * OK-biased collector.
+     * <p>
+     * This will return OK values, unless there are none; then Err values will be returned.
+     * If there are no Err values (and no OK values), an OK with an empty List will be returned.
+     * </p>
+     *
+     * @param <OK>  OK type
+     * @param <ERR> Err type
+     * @return A Result containing a List of OK or Err values as described above.
+     */
     static <OK, ERR> Collector<Result<OK, ERR>, ?, Result<List<OK>, List<ERR>>> okBiasedCollector() {
-        return Collector.<Result<OK, ERR>, Accumulator<OK,ERR>, Result<List<OK>, List<ERR>>>of(
+        return Collector.<Result<OK, ERR>, Accumulator<OK, ERR>, Result<List<OK>, List<ERR>>>of(
                 Accumulator::new,
                 ResultCollectors::add,
                 Accumulator::append,
@@ -28,35 +60,58 @@ public interface ResultCollectors {
         );
     }
 
-    static <OK, ERR> Collector<Result<OK, ERR>, ?, Both<OK, ERR>> both() {
-        return Collector.<Result<OK, ERR>, Accumulator<OK,ERR>, Both<OK,ERR>>of(
+    /**
+     * Unbiased Result collector.
+     * <p>
+     * This will return <b>both</b> OK and Err values
+     * </p>
+     *
+     * @param <OK>  OK type
+     * @param <ERR> Err type
+     * @return Tuple containing OK and Err values
+     */
+    static <OK, ERR> Collector<Result<OK, ERR>, ?, OKsAndErrs<OK, ERR>> both() {
+        return Collector.<Result<OK, ERR>, Accumulator<OK, ERR>, OKsAndErrs<OK, ERR>>of(
                 Accumulator::new,
                 ResultCollectors::add,
                 Accumulator::append,
-                accum -> new Both<>( accum.okList, accum.errList )
+                accum -> new OKsAndErrs<>( accum.okList, accum.errList )
 
         );
     }
 
 
-
-    static private <OK, ERR> void add(Accumulator<OK,ERR> listBox, Result<OK,ERR> result) {
+    static private <OK, ERR> void add(Accumulator<OK, ERR> listBox, Result<OK, ERR> result) {
         switch (result) {
-                case Result.OK<OK, ERR> ok -> listBox.okList.add( ok.get() );
-                case Result.Err<OK, ERR> err -> listBox.errList.add( err.get() );
-            }
+            case Result.OK<OK, ERR> ok -> listBox.okList.add( ok.get() );
+            case Result.Err<OK, ERR> err -> listBox.errList.add( err.get() );
+        }
     }
 
 
-
-
-    record Both<OK, ERR>(List<OK> oks, List<ERR> errs) {
-
-        public Both {
-            Objects.requireNonNull( oks );
-            Objects.requireNonNull( errs );
+    /**
+     * Tuple containing lists of OK and Err values
+     * <p>
+     *     Contained lists are immutable and never null, but may be empty.
+     * </p>
+     *
+     * @param oks OK values
+     * @param errs Err values
+     * @param <OK> OK type
+     * @param <ERR> Err type
+     */
+    record OKsAndErrs<OK, ERR>(@NotNull List<OK> oks, @NotNull List<ERR> errs) {
+
+        /**
+         * Create a OKsAndErrs
+         * @param oks OK values
+         * @param errs Err values
+         */
+        public OKsAndErrs {
+            requireNonNull( oks );
+            requireNonNull( errs );
             oks = List.copyOf( oks );
-            errs = List.copyOf( errs);
+            errs = List.copyOf( errs );
         }
 
     }
diff --git a/src/main/java/net/xyzsd/dichotomy/collectors/package-info.java b/src/main/java/net/xyzsd/dichotomy/collectors/package-info.java
new file mode 100644
index 0000000..ddbc278
--- /dev/null
+++ b/src/main/java/net/xyzsd/dichotomy/collectors/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Customized Stream Collectors for Either and Result types.
+ */
+package net.xyzsd.dichotomy.collectors;
\ No newline at end of file
diff --git a/src/test/java/net/xyzsd/dichotomy/collectors/EitherCollectorsTest.java b/src/test/java/net/xyzsd/dichotomy/collectors/EitherCollectorsTest.java
new file mode 100644
index 0000000..cf5a1b9
--- /dev/null
+++ b/src/test/java/net/xyzsd/dichotomy/collectors/EitherCollectorsTest.java
@@ -0,0 +1,108 @@
+package net.xyzsd.dichotomy.collectors;
+
+import net.xyzsd.dichotomy.Either;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class EitherCollectorsTest {
+
+
+    List<Either<Integer,String>> RESLIST = List.of(
+            Either.ofRight("First"),
+            Either.ofRight("Second"),
+            Either.ofLeft(-3),
+            Either.ofRight("Fourth"),
+            Either.ofRight("Fifth"),
+            Either.ofLeft( -6)
+    );
+
+    List<Either<Integer,String>> RESLIST_EMPTY = List.of();
+    List<Either<Integer,String>> RESLIST_ONLY_SUCCESS = List.of(
+            Either.ofRight("First"),
+            Either.ofRight("Second")
+    );
+
+    List<Either<Integer,String>> RESLIST_ONLY_FAIL = List.of(
+            Either.ofLeft(-111),
+            Either.ofLeft(-222)
+    );
+
+
+
+    @Test
+    void collector() {
+        assertEquals(
+                Either.ofLeft( List.of(-3, -6) ),
+                RESLIST.stream().collect( EitherCollectors.collector() )
+        );
+
+        assertEquals(
+                Either.ofRight(List.of("First","Second")),
+                RESLIST_ONLY_SUCCESS.stream().collect( EitherCollectors.collector() )
+        );
+
+        assertEquals(
+                Either.ofLeft(List.of(-111,-222)),
+                RESLIST_ONLY_FAIL.stream().collect( EitherCollectors.collector() )
+        );
+
+        assertEquals(
+                Either.ofLeft(List.of()),
+                RESLIST_EMPTY.stream().collect( EitherCollectors.collector() )
+        );
+    }
+
+    @Test
+    void rightBiasedCollector() {
+        assertEquals(
+                Either.ofRight( List.of("First", "Second", "Fourth", "Fifth") ),
+                RESLIST.stream().collect( EitherCollectors.rightBiasedCollector() )
+        );
+
+        assertEquals(
+                Either.ofRight( List.of("First", "Second") ),
+                RESLIST_ONLY_SUCCESS.stream().collect( EitherCollectors.rightBiasedCollector() )
+        );
+
+        assertEquals(
+                Either.ofLeft( List.of(-111,-222) ),
+                RESLIST_ONLY_FAIL.stream().collect( EitherCollectors.rightBiasedCollector() )
+        );
+
+        assertEquals(
+                Either.ofRight( List.of() ),
+                RESLIST_EMPTY.stream().collect( EitherCollectors.rightBiasedCollector() )
+        );
+    }
+
+    @Test
+    void both() {
+        assertEquals(
+                new EitherCollectors.LeftsAndRights<>(
+                        List.of(-3, -6),
+                        List.of("First", "Second", "Fourth", "Fifth") ),
+                RESLIST.stream().collect( EitherCollectors.both() )
+        );
+
+        assertEquals(
+                new EitherCollectors.LeftsAndRights<>( List.of(),
+                        List.of("First", "Second") ),
+                RESLIST_ONLY_SUCCESS.stream().collect( EitherCollectors.both() )
+        );
+
+        assertEquals(
+                new EitherCollectors.LeftsAndRights<>( List.of(-111,-222), List.of() ),
+                RESLIST_ONLY_FAIL.stream().collect( EitherCollectors.both() )
+        );
+
+        assertEquals(
+                new EitherCollectors.LeftsAndRights<>( List.of(),List.of() ),
+                RESLIST_EMPTY.stream().collect( EitherCollectors.both() )
+        );
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/src/test/java/net/xyzsd/dichotomy/collectors/ResultCollectorsTest.java b/src/test/java/net/xyzsd/dichotomy/collectors/ResultCollectorsTest.java
index 3bc4b15..c9489b0 100644
--- a/src/test/java/net/xyzsd/dichotomy/collectors/ResultCollectorsTest.java
+++ b/src/test/java/net/xyzsd/dichotomy/collectors/ResultCollectorsTest.java
@@ -2,11 +2,10 @@
 
 import net.xyzsd.dichotomy.Result;
 import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
 
 import java.util.List;
 
-import static org.junit.jupiter.api.Assertions.*;
-
 class ResultCollectorsTest {
 
     List<Result<String,Integer>> RESLIST = List.of(
@@ -29,43 +28,75 @@ class ResultCollectorsTest {
             Result.ofErr(-222)
             );
 
+
+
     @Test
     void collector() {
-        Result<List<String>, List<Integer>> collect = RESLIST.stream().collect( ResultCollectors.collector() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.collector() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.collector() );
-        System.out.println(collect);
-        collect = RESLIST_EMPTY.stream().collect( ResultCollectors.collector() );
-        System.out.println(collect);
-        throw new UnsupportedOperationException("TODO: *validate*");
+        assertEquals(
+                Result.ofErr( List.of(-3, -6) ),
+                RESLIST.stream().collect( ResultCollectors.collector() )
+        );
+
+        assertEquals(
+                Result.ofOK(List.of("First","Second")),
+                RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.collector() )
+        );
+
+        assertEquals(
+                Result.ofErr(List.of(-111,-222)),
+                RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.collector() )
+        );
+
+        assertEquals(
+                Result.ofErr(List.of()),
+                RESLIST_EMPTY.stream().collect( ResultCollectors.collector() )
+        );
     }
 
     @Test
     void okBiasedCollector() {
-        Result<List<String>, List<Integer>> collect = RESLIST.stream().collect( ResultCollectors.okBiasedCollector() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.okBiasedCollector() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.okBiasedCollector() );
-        System.out.println(collect);
-        collect = RESLIST_EMPTY.stream().collect( ResultCollectors.okBiasedCollector() );
-        System.out.println(collect);
-        throw new UnsupportedOperationException("TODO: *validate*");
+        assertEquals(
+                Result.ofOK( List.of("First", "Second", "Fourth", "Fifth") ),
+                RESLIST.stream().collect( ResultCollectors.okBiasedCollector() )
+        );
+
+        assertEquals(
+                Result.ofOK( List.of("First", "Second") ),
+                RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.okBiasedCollector() )
+        );
+
+        assertEquals(
+                Result.ofErr( List.of(-111,-222) ),
+                RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.okBiasedCollector() )
+        );
+
+        assertEquals(
+                Result.ofOK( List.of() ),
+                RESLIST_EMPTY.stream().collect( ResultCollectors.okBiasedCollector() )
+        );
     }
 
     @Test
     void both() {
-        ResultCollectors.Both<String, Integer> collect = RESLIST.stream().collect( ResultCollectors.both() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.both() );
-        System.out.println(collect);
-        collect = RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.both() );
-        System.out.println(collect);
-        collect = RESLIST_EMPTY.stream().collect( ResultCollectors.both() );
-        System.out.println(collect);
-        throw new UnsupportedOperationException("TODO: *validate*");
+        assertEquals(
+                new ResultCollectors.OKsAndErrs<>( List.of("First", "Second", "Fourth", "Fifth"),List.of(-3,-6) ),
+                RESLIST.stream().collect( ResultCollectors.both() )
+        );
+
+        assertEquals(
+                new ResultCollectors.OKsAndErrs<>( List.of("First", "Second"),List.of() ),
+                RESLIST_ONLY_SUCCESS.stream().collect( ResultCollectors.both() )
+        );
+
+        assertEquals(
+                new ResultCollectors.OKsAndErrs<>( List.of(),List.of(-111,-222) ),
+                RESLIST_ONLY_FAIL.stream().collect( ResultCollectors.both() )
+        );
+
+        assertEquals(
+                new ResultCollectors.OKsAndErrs<>( List.of(),List.of() ),
+                RESLIST_EMPTY.stream().collect( ResultCollectors.both() )
+        );
     }
 
 }
\ No newline at end of file