add util classes from org.xbib.net project
This commit is contained in:
parent
8ea1738465
commit
085debd1fe
8 changed files with 433 additions and 0 deletions
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<T> extends AbstractList<T> 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<T> list, T[] t) {
|
||||||
|
this(list.toArray(t), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableList(List<T> 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 <T> ImmutableList<T> of() {
|
||||||
|
return new ImmutableList<>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableList<T> of(List<T> list, T[] t) {
|
||||||
|
return new ImmutableList<>(list, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableList<T> of(List<T> list, T[] t, boolean filterNull) {
|
||||||
|
return new ImmutableList<>(list, t, filterNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableList<T> of(T[] array) {
|
||||||
|
return new ImmutableList<>(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableList<T> 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> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<T> extends AbstractSet<T> {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The internal array. The constructors copy values into this array and the array is never changed.
|
||||||
|
*/
|
||||||
|
private final T[] array;
|
||||||
|
|
||||||
|
public ImmutableSet(Set<T> set, T[] t) {
|
||||||
|
this(set.toArray(t), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableSet(Set<T> 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 <T> ImmutableSet<T> of() {
|
||||||
|
return new ImmutableSet<>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableSet<T> of(Set<T> set, T[] t) {
|
||||||
|
return new ImmutableSet<>(set, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableSet<T> of(Set<T> set, T[] t, boolean filterNull) {
|
||||||
|
return new ImmutableSet<>(set, t, filterNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableSet<T> of(T[] array) {
|
||||||
|
return new ImmutableSet<>(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> ImmutableSet<T> of(T[] array, boolean filterNull) {
|
||||||
|
return new ImmutableSet<>(array, filterNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Builder<T> builder() {
|
||||||
|
return new Builder<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> 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> 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<T> {
|
||||||
|
|
||||||
|
private final Set<T> set = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
private Builder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> add(T t) {
|
||||||
|
set.add(t);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableSet<T> build(T[] t) {
|
||||||
|
return new ImmutableSet<>(set, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <K> the key type parameter
|
||||||
|
* @param <V> the vale type parameter
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
|
||||||
|
|
||||||
|
private final int cacheSize;
|
||||||
|
|
||||||
|
public LRUCache(int cacheSize) {
|
||||||
|
super(16, 0.75f, true);
|
||||||
|
this.cacheSize = cacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||||
|
return size() > cacheSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <K> the key type parameter
|
||||||
|
* @param <V> the value type parameter
|
||||||
|
*/
|
||||||
|
public class Pair<K, V> implements Comparable<Pair<K, V>> {
|
||||||
|
|
||||||
|
private final K key;
|
||||||
|
|
||||||
|
private final V value;
|
||||||
|
|
||||||
|
Pair(K key, V value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> Pair<K, V> 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<K, V> pair) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.xbib.datastructures.common;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface PairValidator extends Function<Pair<String, Object>, Pair<String, Object>> {
|
||||||
|
}
|
|
@ -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<Integer> 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<Integer> immutableList = ImmutableList.of(Arrays.asList(1, 2, 3), new Integer[0]);
|
||||||
|
assertEquals("[1, 2, 3]", immutableList.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStream() {
|
||||||
|
ImmutableList<Integer> 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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Integer> 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<Integer> 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<Integer> 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());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue