package io.gitlab.jfronny.commons.tuple; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.Function; public record Tuple(@Nullable T1 left, @Nullable T2 right) { @Contract(pure = true) @NotNull public static Tuple of(@Nullable T1 left, @Nullable T2 right) { return new Tuple<>(left, right); } @Contract(pure = true) @NotNull public static Tuple from(@NotNull Map.Entry entry) { Objects.requireNonNull(entry); return new Tuple<>(entry.getKey(), entry.getValue()); } @Contract(pure = true) @NotNull public Tuple mapLeft(@NotNull Function mapper) { return new Tuple<>(Objects.requireNonNull(mapper).apply(left), right); } @Contract(pure = true) @NotNull public Tuple mapRight(@NotNull Function mapper) { return new Tuple<>(left, Objects.requireNonNull(mapper).apply(right)); } @Contract(pure = true) @NotNull public Tuple swap() { return new Tuple<>(right, left); } @Contract(pure = true) public static Set> from(@NotNull Map map) { Objects.requireNonNull(map); return new AbstractSet<>() { @Override public int size() { return map.size(); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public boolean contains(Object o) { if (o instanceof Tuple tup) { if (map.containsKey(tup.left) && map.get(tup.left) == tup.right) return true; } if (map.containsKey(o)) return true; return false; } @NotNull @Override public Iterator> iterator() { return map.entrySet().stream().map(Tuple::from).iterator(); } @NotNull @Override public Object[] toArray() { return map.entrySet().stream().map(Tuple::from).toArray(); } @Override public boolean add(Tuple t1T2Tuple) { return map.put(t1T2Tuple.left, t1T2Tuple.right) == null; } @Override public boolean remove(Object o) { if (o instanceof Tuple t) { return map.remove(t.left, t.right); } return map.remove(o) != null; } @Override public void clear() { map.clear(); } }; } }