|
| 1 | +# Either - Java Implementation |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This project provides a Java implementation of Scala's `Either` type, a functional data structure representing a value of one of two possible types (a disjoint union). By convention, `Left` represents failure/error cases and `Right` represents success cases. |
| 6 | + |
| 7 | +## Project Structure |
| 8 | + |
| 9 | +``` |
| 10 | +either/ |
| 11 | +├── src/main/java/stream/header/ |
| 12 | +│ └── Either.java # Main Either implementation |
| 13 | +├── pom.xml # Maven configuration |
| 14 | +└── CLAUDE.md # This file |
| 15 | +``` |
| 16 | + |
| 17 | +## Key Information |
| 18 | + |
| 19 | +- **Language**: Java 17+ |
| 20 | +- **Build Tool**: Maven (use `./mvnw` wrapper) |
| 21 | +- **Package**: `stream.header` |
| 22 | +- **Main Class**: `Either<L, R>` (sealed interface with `Left` and `Right` records) |
| 23 | + |
| 24 | +## Either API |
| 25 | + |
| 26 | +### Creation |
| 27 | +```java |
| 28 | +Either<String, Integer> right = Either.right(42); |
| 29 | +Either<String, Integer> left = Either.left("error"); |
| 30 | +``` |
| 31 | + |
| 32 | +### Core Operations (Right-biased) |
| 33 | +- `map(Function)` - Transform Right value |
| 34 | +- `flatMap(Function)` - Chain Either-returning operations |
| 35 | +- `mapLeft(Function)` - Transform Left value |
| 36 | +- `fold(Function, Function)` - Pattern match on Left or Right |
| 37 | +- `getOrElse(T)` - Extract Right or default value |
| 38 | +- `filterOrElse(Predicate, Supplier)` - Filter Right value |
| 39 | + |
| 40 | +### Querying |
| 41 | +- `isLeft()` / `isRight()` - Check which side |
| 42 | +- `contains(R)` - Check if Right equals value |
| 43 | +- `exists(Predicate)` - Test Right value |
| 44 | +- `getLeft()` / `getRight()` - Unsafe extraction (throws if wrong side) |
| 45 | + |
| 46 | +### Conversion |
| 47 | +- `toOptional()` - Convert Right to Optional |
| 48 | +- `toOptionalLeft()` - Convert Left to Optional |
| 49 | +- `swap()` - Exchange Left and Right |
| 50 | + |
| 51 | +### Side Effects |
| 52 | +- `forEach(Consumer)` - Apply action to Right |
| 53 | +- `forEachLeft(Consumer)` - Apply action to Left |
| 54 | + |
| 55 | +## Build Commands |
| 56 | + |
| 57 | +```bash |
| 58 | +# Compile |
| 59 | +./mvnw compile |
| 60 | + |
| 61 | +# Run tests |
| 62 | +./mvnw test |
| 63 | + |
| 64 | +# Package |
| 65 | +./mvnw package |
| 66 | + |
| 67 | +# Clean |
| 68 | +./mvnw clean |
| 69 | +``` |
| 70 | + |
| 71 | +## Design Decisions |
| 72 | + |
| 73 | +1. **Sealed Interface**: Uses Java 17 sealed interfaces for exhaustive pattern matching |
| 74 | +2. **Records**: Left and Right are immutable records |
| 75 | +3. **Right-biased**: All monadic operations (map, flatMap) operate on Right, matching modern Scala behavior |
| 76 | +4. **Null Safety**: Both Left and Right reject null values |
| 77 | +5. **Fail-fast**: Methods validate null parameters immediately |
| 78 | + |
| 79 | +## Usage Example |
| 80 | + |
| 81 | +```java |
| 82 | +import stream.header.Either; |
| 83 | + |
| 84 | +public class Example { |
| 85 | + public static Either<String, Integer> divide(int a, int b) { |
| 86 | + if (b == 0) { |
| 87 | + return Either.left("Division by zero"); |
| 88 | + } |
| 89 | + return Either.right(a / b); |
| 90 | + } |
| 91 | + |
| 92 | + public static void main(String[] args) { |
| 93 | + Either<String, Integer> result = divide(10, 2) |
| 94 | + .map(x -> x * 2) |
| 95 | + .flatMap(x -> divide(x, 5)); |
| 96 | + |
| 97 | + String message = result.fold( |
| 98 | + error -> "Error: " + error, |
| 99 | + value -> "Result: " + value |
| 100 | + ); |
| 101 | + |
| 102 | + System.out.println(message); // "Result: 4" |
| 103 | + } |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +## Conventions |
| 108 | + |
| 109 | +- **Left**: Represents errors, failures, or exceptional cases (typically `String`, `Exception`, or custom error types) |
| 110 | +- **Right**: Represents successful results and normal values |
| 111 | +- All operations are right-biased (operate on Right, short-circuit on Left) |
0 commit comments