From 085debd1feb86cecb15f4ea09ad606c225280a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Prante?= Date: Sat, 27 Aug 2022 19:17:05 +0200 Subject: [PATCH] add util classes from org.xbib.net project --- .../common/CharBufferReader.java | 68 +++++++++++ .../datastructures/common/ImmutableList.java | 89 ++++++++++++++ .../datastructures/common/ImmutableSet.java | 112 ++++++++++++++++++ .../xbib/datastructures/common/LRUCache.java | 26 ++++ .../org/xbib/datastructures/common/Pair.java | 56 +++++++++ .../datastructures/common/PairValidator.java | 6 + .../common/ImmutableListTest.java | 32 +++++ .../common/ImmutableSetTest.java | 44 +++++++ 8 files changed, 433 insertions(+) create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/CharBufferReader.java create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableList.java create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableSet.java create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/LRUCache.java create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/Pair.java create mode 100644 datastructures-common/src/main/java/org/xbib/datastructures/common/PairValidator.java create mode 100644 datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableListTest.java create mode 100644 datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableSetTest.java diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/CharBufferReader.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/CharBufferReader.java new file mode 100644 index 0000000..1e8b9b4 --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/CharBufferReader.java @@ -0,0 +1,68 @@ +package org.xbib.datastructures.common; + +import java.io.Reader; +import java.nio.CharBuffer; + +public class CharBufferReader extends Reader { + + private final CharBuffer charBuffer; + + public CharBufferReader(CharBuffer buffer) { + buffer.mark(); + charBuffer = buffer; + } + + @Override + public int read() { + if (!charBuffer.hasRemaining()) { + return -1; + } + return charBuffer.get(); + } + + @Override + public int read(char[] cbuf, int off, int len) { + int remaining = charBuffer.remaining(); + if (remaining <= 0) { + return -1; + } + int length = Math.min(len, remaining); + charBuffer.get(cbuf, off, length); + return length; + } + + @Override + public long skip(long n) { + if (n < 0L) { + return 0L; + } + int skipped = Math.min((int) n, charBuffer.remaining()); + charBuffer.position(charBuffer.position() + skipped); + return skipped; + } + + @Override + public boolean ready() { + return true; + } + + @Override + public boolean markSupported() { + return true; + } + + @Override + public void mark(int readAheadLimit) { + charBuffer.mark(); + } + + @Override + public void reset() { + charBuffer.reset(); + } + + @Override + public void close() { + charBuffer.position(charBuffer.limit()); + } +} diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableList.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableList.java new file mode 100644 index 0000000..ef3c9e9 --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableList.java @@ -0,0 +1,89 @@ +package org.xbib.datastructures.common; + +import java.util.AbstractList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.RandomAccess; + +/** + * A light-weight immutable list. + */ +public final class ImmutableList extends AbstractList implements RandomAccess { + + /* + * The internal array. The constructors copy values into this array and the array is never changed. + */ + private final T[] array; + + public ImmutableList(List list, T[] t) { + this(list.toArray(t), false); + } + + public ImmutableList(List list, T[] t, boolean filterNull) { + this(list.toArray(t), filterNull); + } + + public ImmutableList(T[] array) { + this(array, false); + } + + public ImmutableList(T[] array, boolean filterNulls) { + this.array = filterNulls ? arrayFilteringNull(array) : array; + } + + public static ImmutableList of() { + return new ImmutableList<>(null); + } + + public static ImmutableList of(List list, T[] t) { + return new ImmutableList<>(list, t); + } + + public static ImmutableList of(List list, T[] t, boolean filterNull) { + return new ImmutableList<>(list, t, filterNull); + } + + public static ImmutableList of(T[] array) { + return new ImmutableList<>(array); + } + + public static ImmutableList of(T[] array, boolean filterNull) { + return new ImmutableList<>(array, filterNull); + } + + @Override + public T get(int index) { + return array != null ? array[index] : null; + } + + @Override + public int size() { + return array != null ? array.length : 0; + } + + @Override + public boolean contains(Object o) { + if (array != null) { + for (T t : array) { + if (t == o) { + return true; + } + } + } + return false; + } + + private static T[] arrayFilteringNull(T[] views) { + Objects.requireNonNull(views); + int end = 0; + int length = views.length; + for (int i = 0; i < length; i++) { + T view = views[i]; + if (view != null) { + views[end++] = view; + } + } + return end == length ? views : Arrays.copyOf(views, end); + } +} diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableSet.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableSet.java new file mode 100644 index 0000000..aef8870 --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/ImmutableSet.java @@ -0,0 +1,112 @@ +package org.xbib.datastructures.common; + +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +/** + * A light-weight immutable set. + */ +public final class ImmutableSet extends AbstractSet { + + /* + * The internal array. The constructors copy values into this array and the array is never changed. + */ + private final T[] array; + + public ImmutableSet(Set set, T[] t) { + this(set.toArray(t), false); + } + + public ImmutableSet(Set set, T[] t, boolean filterNull) { + this(set.toArray(t), filterNull); + } + + public ImmutableSet(T[] array) { + this(array, false); + } + + public ImmutableSet(T[] array, boolean filterNulls) { + this.array = filterNulls ? arrayFilteringNull(array) : array; + } + + public static ImmutableSet of() { + return new ImmutableSet<>(null); + } + + public static ImmutableSet of(Set set, T[] t) { + return new ImmutableSet<>(set, t); + } + + public static ImmutableSet of(Set set, T[] t, boolean filterNull) { + return new ImmutableSet<>(set, t, filterNull); + } + + public static ImmutableSet of(T[] array) { + return new ImmutableSet<>(array); + } + + public static ImmutableSet of(T[] array, boolean filterNull) { + return new ImmutableSet<>(array, filterNull); + } + + public static Builder builder() { + return new Builder<>(); + } + + @Override + public Iterator iterator() { + return array != null ? Arrays.stream(array).sorted().distinct().iterator() : Collections.emptyIterator(); + } + + @Override + public int size() { + return array != null? array.length : 0; + } + + @Override + public boolean contains(Object o) { + if (array != null) { + for (T t : array) { + if (t == o) { + return true; + } + } + } + return false; + } + + private static T[] arrayFilteringNull(T[] views) { + Objects.requireNonNull(views); + int end = 0; + int length = views.length; + for (int i = 0; i < length; i++) { + T view = views[i]; + if (view != null) { + views[end++] = view; + } + } + return end == length ? views : Arrays.copyOf(views, end); + } + + public static class Builder { + + private final Set set = new LinkedHashSet<>(); + + private Builder() { + } + + public Builder add(T t) { + set.add(t); + return this; + } + + public ImmutableSet build(T[] t) { + return new ImmutableSet<>(set, t); + } + } +} diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/LRUCache.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/LRUCache.java new file mode 100644 index 0000000..39bb158 --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/LRUCache.java @@ -0,0 +1,26 @@ +package org.xbib.datastructures.common; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A simple LRU cache, based on a {@link LinkedHashMap}. + * + * @param the key type parameter + * @param the vale type parameter + */ +@SuppressWarnings("serial") +public class LRUCache extends LinkedHashMap { + + private final int cacheSize; + + public LRUCache(int cacheSize) { + super(16, 0.75f, true); + this.cacheSize = cacheSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > cacheSize; + } +} diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/Pair.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/Pair.java new file mode 100644 index 0000000..2bcc143 --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/Pair.java @@ -0,0 +1,56 @@ +package org.xbib.datastructures.common; + +import java.util.Objects; + +/** + * A pair of data, allowing null for key and value, in difference to Map.entry(). + * + * @param the key type parameter + * @param the value type parameter + */ +public class Pair implements Comparable> { + + private final K key; + + private final V value; + + Pair(K key, V value) { + this.key = key; + this.value = value; + } + + public static Pair of(K k, V v) { + return new Pair<>(k, v); + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Pair pair = (Pair) o; + return Objects.equals(key, pair.key) && Objects.equals(value, pair.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + return key + "=" + value; + } + + @Override + public int compareTo(Pair pair) { + return 0; + } +} diff --git a/datastructures-common/src/main/java/org/xbib/datastructures/common/PairValidator.java b/datastructures-common/src/main/java/org/xbib/datastructures/common/PairValidator.java new file mode 100644 index 0000000..e7a241b --- /dev/null +++ b/datastructures-common/src/main/java/org/xbib/datastructures/common/PairValidator.java @@ -0,0 +1,6 @@ +package org.xbib.datastructures.common; + +import java.util.function.Function; + +public interface PairValidator extends Function, Pair> { +} diff --git a/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableListTest.java b/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableListTest.java new file mode 100644 index 0000000..68e56b3 --- /dev/null +++ b/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableListTest.java @@ -0,0 +1,32 @@ +package org.xbib.datastructures.common; + +import java.util.Arrays; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ImmutableListTest { + + @Test + public void testArray() { + ImmutableList immutableList = ImmutableList.of(); + assertEquals(0, immutableList.size()); + assertEquals("[]", immutableList.toString()); + Integer[] i = new Integer[] { 1, 2, 3 }; + immutableList = ImmutableList.of(i); + assertEquals("[1, 2, 3]", immutableList.toString()); + } + + @Test + public void testList() { + ImmutableList immutableList = ImmutableList.of(Arrays.asList(1, 2, 3), new Integer[0]); + assertEquals("[1, 2, 3]", immutableList.toString()); + } + + @Test + public void testStream() { + ImmutableList immutableList = ImmutableList.of(Arrays.asList(1, 2, 3), new Integer[0]); + assertEquals(3L, immutableList.size()); + assertEquals("[2, 3, 4]", immutableList.stream().map(i -> i + 1).collect(Collectors.toList()).toString()); + } +} diff --git a/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableSetTest.java b/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableSetTest.java new file mode 100644 index 0000000..d4d3d54 --- /dev/null +++ b/datastructures-common/src/test/java/org/xbib/datastructures/common/ImmutableSetTest.java @@ -0,0 +1,44 @@ +package org.xbib.datastructures.common; + +import java.util.Set; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ImmutableSetTest { + + @Test + public void testArray() { + ImmutableSet immutableSet = ImmutableSet.of(); + assertEquals("[]", immutableSet.toString()); + Integer[] i = new Integer[] { }; + immutableSet = ImmutableSet.of(i); + assertEquals("[]", immutableSet.toString()); + i = new Integer[] { 1 }; + immutableSet = ImmutableSet.of(i); + assertEquals("[1]", immutableSet.toString()); + i = new Integer[] { 1, 1 }; + immutableSet = ImmutableSet.of(i); + assertEquals("[1]", immutableSet.toString()); + i = new Integer[] { 1, 2 }; + immutableSet = ImmutableSet.of(i); + assertEquals("[1, 2]", immutableSet.toString()); + } + + @Test + public void testSet() { + ImmutableSet immutableSet = ImmutableSet.of(Set.of(1), new Integer[0]); + assertEquals("[1]", immutableSet.toString()); + immutableSet = ImmutableSet.of(Set.of(1, 2), new Integer[0]); + assertEquals("[1, 2]", immutableSet.toString()); + immutableSet = ImmutableSet.of(Set.of(1, 2, 3), new Integer[0]); + assertEquals("[1, 2, 3]", immutableSet.toString()); + } + + @Test + public void testStream() { + ImmutableSet immutableSet = ImmutableSet.of(Set.of(1, 2, 3), new Integer[0]); + assertEquals(3L, immutableSet.size()); + assertEquals("[2, 3, 4]", immutableSet.stream().map(i -> i + 1).collect(Collectors.toList()).toString()); + } +}