├── src ├── main │ └── java │ │ └── yk │ │ ├── todo.txt │ │ └── jcommon │ │ ├── collections │ │ ├── Function_T_int.java │ │ ├── Function_float_T.java │ │ ├── Consumer3.java │ │ ├── Consumer4.java │ │ ├── !about.txt │ │ ├── Test.java │ │ ├── Tuple.java │ │ ├── Array2.java │ │ ├── YSet.java │ │ ├── YHashSet.java │ │ ├── YHashSetWrapper.java │ │ ├── YMap.java │ │ ├── YCollectionWrapper.java │ │ ├── YCollections.java │ │ ├── YList.java │ │ ├── YHashMap.java │ │ ├── YArrayList.java │ │ └── YCollection.java │ │ └── progress.txt └── test │ └── java │ └── yk │ └── jcommon │ └── collections │ ├── TestYArrayList.java │ ├── TestYHashMap.java │ └── TestCollections.java ├── LICENSE ├── pom.xml └── README.md /src/main/java/yk/todo.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Function_T_int.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | public interface Function_T_int { 4 | T apply(int i); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Function_float_T.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | public interface Function_float_T { 4 | float apply(T t); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Consumer3.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: yuri 6 | * Date: 19/11/15 7 | * Time: 17:05 8 | */ 9 | public interface Consumer3 { 10 | 11 | void accept(T1 t1, T2 t2, T3 t3); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Consumer4.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: yuri 6 | * Date: 19/11/15 7 | * Time: 17:05 8 | */ 9 | public interface Consumer4 { 10 | 11 | void accept(T1 t1, T2 t2, T3 t3, T4 t4); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/progress.txt: -------------------------------------------------------------------------------- 1 | 2 | 06.03.17 3 | FileWatcher2 - more stable simple file watching 4 | 5 | 18.07.17 6 | password tuning (exception characters, refactoring, info) 7 | 8 | 18.07.17 9 | password tuning (secure random) 10 | 11 | 28.12.17 12 | separated yincubator 13 | 14 | 13.04.18 15 | Vec logic generator WIP 16 | 17 | 14.04.18 18 | refactorings 19 | 20 | 15.04.18 21 | fill in Vec3f with auto-generated 22 | 23 | //TODO 24 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/!about.txt: -------------------------------------------------------------------------------- 1 | 2 | TODO 3 | 4 | immutable empty YList, YSet, YMap 5 | 6 | 7 | 8 | 9 | done 10 | 11 | zip iterator 12 | YCollection.mapWith(YCollection, Mapper) - Mapper is function that takes two args - one from each collection 13 | something artful with maps? 14 | YMap YMap.mapValues(Function), instead of current map, maybe 15 | YMap - mapping must can return not pares, but just elements 16 | containsAny 17 | max/min with evaluator 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Test.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: yuri 8 | * Date: 8/13/14 9 | * Time: 9:47 PM 10 | */ 11 | public class Test { 12 | 13 | public static void main(String[] args) { 14 | String names = YArrayList.al(new File("/home/yuri/").listFiles()) 15 | .filter(File::isDirectory) //only dirs 16 | .map(File::getName) //get name 17 | .filter(n -> n.startsWith(".")) //only invisible 18 | .sorted() //sorted 19 | .reduce("", (r, n) -> r + ", " + n); //to print fine 20 | System.out.println(names); 21 | 22 | //File("/home/yuri")listFiles()f(_.isDirectory)m(_.getName)f(n.startsWith(".")sfl("" _1+", "+_2) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Yuri Kravchik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Tuple.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: yuri 6 | * Date: 2/18/14 7 | * Time: 10:49 AM 8 | */ 9 | public class Tuple { 10 | public A a; 11 | public B b; 12 | 13 | public Tuple(A a, B b) { 14 | this.a = a; 15 | this.b = b; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "Tuple{" + 21 | "a=" + a + 22 | ", b=" + b + 23 | '}'; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object o) { 28 | if (this == o) return true; 29 | if (o == null || getClass() != o.getClass()) return false; 30 | 31 | Tuple tuple = (Tuple) o; 32 | 33 | if (a != null) { 34 | if (!a.equals(tuple.a)) return false; 35 | } else { 36 | if (tuple.a != null) return false; 37 | } 38 | if (b != null) { 39 | if (!b.equals(tuple.b)) return false; 40 | } else { 41 | if (tuple.b != null) return false; 42 | } 43 | 44 | return true; 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | int result; 50 | if (a != null) result = a.hashCode(); 51 | else result = 0; 52 | if (b != null) result = 31 * result + b.hashCode(); 53 | else result = 31 * result + 0; 54 | return result; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/Array2.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | /** 4 | * Kravchik Yuri 5 | * Date: 1/18/12 6 | * Time: 9:09 PM 7 | */ 8 | public class Array2 { 9 | public T[] data; 10 | public final int width; 11 | public final int height; 12 | 13 | public Array2(int width, int height) { 14 | this.width = width; 15 | this.height = height; 16 | data = (T[]) new Object[width * height]; 17 | 18 | } 19 | 20 | public Array2(Array2 other) { 21 | this(other.width, other.height); 22 | for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) set(x, y, other.get(x, y)); 23 | } 24 | 25 | public Array2(int width, int height, T defaultValue) { 26 | this(width, height); 27 | for (int i = 0, tLength = data.length; i < tLength; i++) { 28 | data[i] = defaultValue; 29 | } 30 | } 31 | 32 | private int calcIndex(int x, int y) { 33 | return x + y * width; 34 | } 35 | 36 | private boolean isInRange(int x, int y) { 37 | return x >= 0 && y >= 0 && x < width && y < height; 38 | } 39 | 40 | private int getIndex(int x, int y) { 41 | if (!isInRange(x, y)) throw new Error(x + " " + y + "(of " + width + " " + height + ")"); 42 | return calcIndex(x, y); 43 | 44 | } 45 | 46 | public T get(int x, int y) { 47 | return data[getIndex(x, y)]; 48 | } 49 | 50 | public T set(int x, int y, T value) { 51 | int i = getIndex(x, y); 52 | T old = data[i]; 53 | data[i] = value; 54 | return old; 55 | } 56 | 57 | public static void main(String[] args) { 58 | Array2 ii = new Array2(10, 10); 59 | ii.set(5, 5, 10); 60 | System.out.println(ii.get(5, 5)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/yk/jcommon/collections/TestYArrayList.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static yk.jcommon.collections.YArrayList.al; 7 | import static yk.jcommon.collections.YArrayList.times; 8 | 9 | /** 10 | * Created by Yuri Kravchik on 17.11.2019 11 | */ 12 | public class TestYArrayList { 13 | 14 | @Test 15 | public void testGetOr() { 16 | assertEquals("hello", al().getOr(0, "hello")); 17 | assertEquals("world", al("world").getOr(0, "hello")); 18 | assertEquals("hello", al("world").getOr(-1, "hello")); 19 | assertEquals("hello", al("world").getOr(1, "hello")); 20 | } 21 | 22 | @Test 23 | public void testTimes() { 24 | assertEquals(al(), times(-1, i -> "_" + i));//maybe it is better to throw an exception 25 | assertEquals(al(), times(0, i -> "_" + i)); 26 | assertEquals(al("_0", "_1", "_2"), times(3, i -> "_" + i)); 27 | } 28 | 29 | @Test 30 | public void testRemoveFast() { 31 | assertEquals(al(), rf(al("a"), 0)); 32 | assertEquals(al("b"), rf(al("a", "b"), 0)); 33 | assertEquals(al("c", "b"), rf(al("a", "b", "c"), 0)); 34 | assertEquals(al("a", "c"), rf(al("a", "b", "c"), 1)); 35 | assertEquals(al("a", "b"), rf(al("a", "b", "c"), 2)); 36 | } 37 | 38 | @Test 39 | public void testZipWith() { 40 | assertEquals(al(), al().zipWith(al(), (a, b) -> null)); 41 | assertEquals(al(), al("a").zipWith(al(), (a, b) -> a + b)); 42 | assertEquals(al("ab"), al("a").zipWith(al("b"), (a, b) -> a + b)); 43 | assertEquals(al(), al().zipWith(al("b"), (a, b) -> a + b)); 44 | } 45 | 46 | private static YArrayList rf(YArrayList src, int i) { 47 | T old = src.get(i); 48 | T t = src.removeFast(i); 49 | assertEquals(old, t); 50 | return src; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YSet.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Iterator; 5 | import java.util.Set; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | 9 | import static yk.jcommon.collections.YHashSet.hs; 10 | 11 | /** 12 | * Created with IntelliJ IDEA. 13 | * User: yuri 14 | * Date: 8/13/14 15 | * Time: 8:53 PM 16 | */ 17 | public interface YSet extends YCollection, Set { 18 | @Override 19 | YSet filter(Predicate predicate); 20 | @Override 21 | YSet map(Function mapper); 22 | @Override 23 | YSet flatMap(Function> mapper); 24 | @Override 25 | YSet cdr(); 26 | 27 | @Override 28 | default YSet toSet() { 29 | return this; 30 | } 31 | 32 | @Override 33 | YSet withAll(Collection c); 34 | @Override 35 | YSet with(T t); 36 | @Override 37 | @SuppressWarnings("unchecked") 38 | YSet with(T... tt); 39 | @Override 40 | YSet withoutAll(Collection tt); 41 | @Override 42 | YSet without(T t); 43 | @Override 44 | @SuppressWarnings("unchecked") 45 | default YSet without(T... tt) { 46 | return withoutAll(hs(tt)); 47 | } 48 | 49 | default YSet intersection(YSet other) { 50 | YSet result = hs(); 51 | for (T t : this) if (other.contains(t))result.add(t); 52 | return result; 53 | } 54 | 55 | @Override 56 | default YSet take(int count) { 57 | YSet result = hs(); 58 | Iterator it = iterator(); 59 | for (int i = 0; i < count && it.hasNext(); i++) result.add(it.next()); 60 | return result; 61 | } 62 | 63 | @Override 64 | default YSet assertSize(int s) { 65 | if (size() != s) { 66 | throw new RuntimeException("Expected size " + s + " but was " + size()); 67 | } 68 | return this; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YHashSet.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Iterator; 5 | import java.util.LinkedHashSet; 6 | import java.util.function.Consumer; 7 | import java.util.function.Function; 8 | import java.util.function.Predicate; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: yuri 13 | * Date: 8/13/14 14 | * Time: 8:53 PM 15 | */ 16 | public class YHashSet extends LinkedHashSet implements YSet { 17 | 18 | @Override 19 | public YCollection emptyInstance() { 20 | return hs(); 21 | } 22 | 23 | public static YHashSet toYSet(Collection source) { 24 | YHashSet result = new YHashSet<>(); 25 | result.addAll(source); 26 | return result; 27 | } 28 | 29 | @SafeVarargs 30 | public static YHashSet hs(T... tt) { 31 | YHashSet result = new YHashSet<>(); 32 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 33 | return result; 34 | } 35 | 36 | public static YHashSet hs() {//to avoid creation of empty array if calling hs(T... tt) 37 | return new YHashSet<>(); 38 | } 39 | 40 | @Override 41 | public YSet filter(Predicate predicate) { 42 | return YCollections.filterSet(this, predicate); 43 | } 44 | 45 | @Override 46 | public YSet map(Function mapper) { 47 | return YCollections.mapSet(this, mapper); 48 | } 49 | 50 | @Override 51 | public YSet flatMap(Function> mapper) { 52 | return YCollections.flatMapSet(this, mapper); 53 | } 54 | 55 | @Override 56 | public YSet cdr() { 57 | YSet result = new YHashSet<>(); 58 | Iterator iterator = this.iterator(); 59 | iterator.next(); 60 | for (; iterator.hasNext(); ) result.add(iterator.next()); 61 | return result; 62 | } 63 | 64 | @Override 65 | public YSet without(T t) { 66 | return YCollections.subSet(this, t); 67 | } 68 | 69 | @Override 70 | public YSet withoutAll(Collection tt) { 71 | return YCollections.subSet(this, tt); 72 | } 73 | 74 | @Override 75 | public YSet withAll(Collection c) { 76 | return YCollections.appendSet(this, c); 77 | } 78 | 79 | @Override 80 | public YSet with(T t) { 81 | return YCollections.appendSet(this, t); 82 | } 83 | 84 | @SafeVarargs 85 | @Override 86 | public final YSet with(T... tt) { 87 | YHashSet result = new YHashSet<>(); 88 | result.addAll(this); 89 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 90 | return result; 91 | } 92 | 93 | public > YSet forThis(Consumer c) { 94 | c.accept((TT)this); 95 | return this; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | yk 6 | jcommon 7 | 0.125-SNAPSHOT 8 | 9 | jar 10 | jcommon 11 | 12 | 13 | 2.0.9 14 | 15 | 16 | UTF-8 17 | 18 | 19 | 20 | install 21 | 22 | 23 | maven-compiler-plugin 24 | 2.0.2 25 | 26 | 1.8 27 | 1.8 28 | UTF8 29 | 30 | 31 | 32 | 33 | compile 34 | testCompile 35 | 36 | 37 | 38 | 39 | 40 | maven-resources-plugin 41 | 2.2 42 | 43 | UTF8 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-source-plugin 50 | 2.2.1 51 | 52 | 53 | attach-sources 54 | verify 55 | 56 | jar-no-fork 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | junit 69 | junit 70 | test 71 | 4.13.1 72 | true 73 | 74 | 75 | 76 | 77 | https://github.com/kravchik/mvn-repo/raw/master 78 | 79 | 80 | snapshot 81 | file://${basedir}/../mvn-repo 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/test/java/yk/jcommon/collections/TestYHashMap.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | import static yk.jcommon.collections.YArrayList.al; 8 | import static yk.jcommon.collections.YHashMap.hm; 9 | import static yk.jcommon.collections.YHashMap.toYMap; 10 | 11 | /** 12 | * Created by Yuri Kravchik on 20.12.2018 13 | */ 14 | public class TestYHashMap { 15 | 16 | @Test 17 | public void testConstructors() { 18 | assertEquals(hm(), new YHashMap()); 19 | assertEquals(hm(), new YHashMap(hm())); 20 | assertEquals(hm("1", "2"), new YHashMap(hm("1", "2"))); 21 | 22 | assertEquals(hm(), toYMap(hm())); 23 | assertEquals(hm("1", "2"), toYMap(hm("1", "2"))); 24 | } 25 | 26 | @Test 27 | public void testFilter() { 28 | assertEquals(hm(), hm().filter((k, v) -> false)); 29 | assertEquals(hm(), hm(1, 2).filter((k, v) -> false)); 30 | assertEquals(hm(1, 2), hm(1, 2).filter((k, v) -> true)); 31 | assertEquals(hm(1, 2), hm(1, 2, 3, 4).filter((k, v) -> k == 1)); 32 | assertEquals(hm(1, 2), hm(1, 2, 3, 4).filter((k, v) -> v == 2)); 33 | } 34 | 35 | @Test 36 | public void testMapToList() { 37 | assertEquals(al(), hm().mapToList((k, v) -> k)); 38 | assertEquals(al(1), hm(1, 2).mapToList((k, v) -> k)); 39 | assertEquals(al(2), hm(1, 2).mapToList((k, v) -> v)); 40 | assertEquals(al(1, 3), hm(1, 2, 3, 4).mapToList((k, v) -> k)); 41 | } 42 | 43 | @Test 44 | public void testMap() { 45 | assertEquals(hm(), hm().map((k, v) -> k+"", (k, v) -> v+"")); 46 | assertEquals(hm(), hm().map(k -> k+"", v -> v)); 47 | assertEquals(hm("1", "2"), hm(1, 2).map((k, v) -> k+"", (k, v) -> v+"")); 48 | assertEquals(hm("1", "2"), hm(1, 2).map(k -> k+"", v -> v+"")); 49 | } 50 | 51 | @Test 52 | public void testMapValues() { 53 | assertEquals(hm(), hm().mapValues((k, v) -> k+"")); 54 | assertEquals(hm(), hm().mapValues(v -> v+"")); 55 | 56 | assertEquals(hm(1, "2"), hm(1, 2).mapValues((k, v) -> v+"")); 57 | assertEquals(hm(1, "2"), hm(1, 2).mapValues(v -> v+"")); 58 | } 59 | 60 | @Test 61 | public void testMapKeys() { 62 | assertEquals(hm(), hm().mapKeys((k, v) -> k+"")); 63 | assertEquals(hm(), hm().mapKeys(v -> v+"")); 64 | 65 | assertEquals(hm("2", 2), hm(1, 2).mapKeys((k, v) -> v+"")); 66 | assertEquals(hm("1", 2), hm(1, 2).mapKeys(k -> k+"")); 67 | } 68 | 69 | @Test 70 | public void testCar() { 71 | assertNull(hm().car()); 72 | assertEquals(new Tuple(1, 2), hm(1, 2).car()); 73 | assertEquals(new Tuple(1, 2), hm(1, 2).first()); 74 | assertEquals(new Tuple(1, 2), hm(1, 2).last()); 75 | assertEquals(new Tuple(3, 4), hm(1, 2, 3, 4).last()); 76 | assertNull(hm().last()); 77 | assertEquals(hm(), hm(1, 2).cdr()); 78 | assertEquals(hm(3, 4), hm(1, 2, 3, 4).cdr()); 79 | } 80 | 81 | @Test 82 | public void testWith() { 83 | assertEquals(hm(1, 2, 3, 4), hm(1, 2).with(3, 4)); 84 | assertEquals(hm(1, 2, 3, 4, 5, 6), hm(1, 2).with(3, 4, 5, 6)); 85 | assertEquals(hm(1, 2, 3, 4), hm(1, 2).with(hm(3, 4))); 86 | 87 | assertEquals(hm(0, 1, 2, 4, 4, 5), hm(0, 1, 2, 3, 4, 5).with(2, 4)); 88 | assertEquals(hm(0, 1, 2, 4, 4, 6), hm(0, 1, 2, 3, 4, 5).with(2, 4, 4, 6)); 89 | assertEquals(hm(0, 1, 2, 4, 4, 5), hm(0, 1, 2, 3, 4, 5).with(hm(2, 4))); 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YHashSetWrapper.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Iterator; 5 | import java.util.Set; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | 9 | public class YHashSetWrapper implements YSet { 10 | private final Set original; 11 | 12 | @Override 13 | public YCollection emptyInstance() { 14 | throw new RuntimeException("Not implemented"); 15 | } 16 | 17 | private static RuntimeException cannotModify() { 18 | return new RuntimeException("Cannot modify wrapper"); 19 | } 20 | 21 | public YHashSetWrapper(Set original) { 22 | this.original = original; 23 | } 24 | 25 | @Override 26 | public YSet filter(Predicate predicate) { 27 | return YCollections.filterSet(original, predicate); 28 | } 29 | 30 | @Override 31 | public YSet map(Function mapper) { 32 | return YCollections.mapSet(original, mapper); 33 | } 34 | 35 | @Override 36 | public YSet flatMap(Function> mapper) { 37 | return YCollections.flatMapSet(original, mapper); 38 | } 39 | 40 | @Override 41 | public YSet cdr() { 42 | YSet result = new YHashSet<>(); 43 | Iterator iterator = original.iterator(); 44 | iterator.next(); 45 | for (; iterator.hasNext(); ) result.add(iterator.next()); 46 | return result; 47 | } 48 | 49 | @Override 50 | public YSet withAll(Collection c) { 51 | return YCollections.appendSet(original, c); 52 | } 53 | 54 | @Override 55 | public YSet with(T t) { 56 | return YCollections.appendSet(original, t); 57 | } 58 | 59 | @Override 60 | public YSet with(T... tt) { 61 | YHashSet result = new YHashSet<>(); 62 | result.addAll(original); 63 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 64 | return result; 65 | } 66 | 67 | @Override 68 | public YSet withoutAll(Collection tt) { 69 | return YCollections.subSet(original, tt); 70 | } 71 | 72 | @Override 73 | public YSet without(T t) { 74 | return YCollections.subSet(original, t); 75 | } 76 | 77 | @Override 78 | public int size() { 79 | return original.size(); 80 | } 81 | 82 | @Override 83 | public boolean isEmpty() { 84 | return original.isEmpty(); 85 | } 86 | 87 | @Override 88 | public boolean contains(Object o) { 89 | return original.contains(o); 90 | } 91 | 92 | @Override 93 | public Iterator iterator() { 94 | return original.iterator(); 95 | } 96 | 97 | @Override 98 | public Object[] toArray() { 99 | return original.toArray(); 100 | } 101 | 102 | @Override 103 | public T1[] toArray(T1[] a) { 104 | return original.toArray(a); 105 | } 106 | 107 | @Override 108 | public boolean add(T t) { 109 | throw cannotModify(); 110 | } 111 | 112 | @Override 113 | public boolean remove(Object o) { 114 | throw cannotModify(); 115 | } 116 | 117 | @Override 118 | public boolean containsAll(Collection c) { 119 | return original.containsAll(c); 120 | } 121 | 122 | @Override 123 | public boolean addAll(Collection c) { 124 | throw cannotModify(); 125 | } 126 | 127 | @Override 128 | public boolean removeAll(Collection c) { 129 | return original.removeAll(c); 130 | } 131 | 132 | @Override 133 | public boolean retainAll(Collection c) { 134 | throw cannotModify(); 135 | } 136 | 137 | @Override 138 | public void clear() { 139 | throw cannotModify(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YMap.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Comparator; 5 | import java.util.Map; 6 | import java.util.function.BiFunction; 7 | import java.util.function.BiPredicate; 8 | import java.util.function.Function; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: yuri 13 | * Date: 8/13/14 14 | * Time: 10:34 PM 15 | */ 16 | public interface YMap extends Map { 17 | Function PASS = o -> o; 18 | BiFunction PASS_FIRST = (o, o2) -> o; 19 | BiFunction PASS_SECOND = (o, o2) -> o2; 20 | 21 | //TODO notContainsKey() 22 | YMap filter(BiPredicate predicate); 23 | YList mapToList(BiFunction mapper); 24 | 25 | YMap map(Function keyMapper, Function valueMapper); 26 | YMap map(BiFunction keyMapper, BiFunction valueMapper); 27 | @Deprecated //use mapValues instead 28 | default YMap map(Function mapper) {return mapValues(mapper);} 29 | @Deprecated //use mapValues instead 30 | default YMap map(BiFunction mapper) {return mapValues(mapper);} 31 | default YMap mapKeys(BiFunction mapper) {return map(mapper, PASS_SECOND);} 32 | default YMap mapKeys(Function mapper) {return map(mapper, PASS);} 33 | default YMap mapValues(BiFunction mapper) {return map(PASS_FIRST, mapper);} 34 | default YMap mapValues(Function mapper) {return map(PASS, mapper);} 35 | 36 | Tuple car(); 37 | YMap cdr(); 38 | Tuple first(); 39 | Tuple last(); 40 | 41 | //TODO first by predicate 42 | 43 | Tuple max(BiFunction evaluator); 44 | V maxValue(Function evaluator); 45 | Tuple min(BiFunction evaluator); 46 | V minValue(Function evaluator); 47 | 48 | boolean isAll(BiPredicate predicate); 49 | boolean isAny(BiPredicate predicate); 50 | 51 | V getOr(K key, V cur); 52 | 53 | @Override 54 | YSet keySet(); 55 | 56 | @Override 57 | YCollection values(); 58 | 59 | YMap with(K k, V v); 60 | YMap with(K k, V v, Object... other); 61 | YMap with(Map kv); 62 | 63 | YMap without(K pKey); 64 | YMap without(Collection keys); 65 | 66 | YMap sorted(Comparator> comparator); 67 | YMap sortedBy(BiFunction evaluator); 68 | 69 | YMap take(int n); 70 | 71 | default void putAll(K k, V v, Object... other) { 72 | put(k, v); 73 | for (int i = 0; i < other.length; i += 2) put((K) other[i], (V) other[i + 1]); 74 | } 75 | 76 | default boolean containsAll(Map whom) { 77 | for (Map.Entry entry : whom.entrySet()) { 78 | if (!containsKey(entry.getKey()) || !get(entry.getKey()).equals(entry.getValue())) return false; 79 | } 80 | return true; 81 | } 82 | 83 | default boolean notEmpty() { 84 | return !isEmpty(); 85 | } 86 | 87 | default String toString(String elementsInfix) { 88 | return toString(elementsInfix, ":"); 89 | } 90 | 91 | default String toString(String elementsInfix, String kvInfix) { 92 | boolean was = false; 93 | StringBuilder sb = new StringBuilder(""); 94 | for (K k : keySet()) { 95 | if (was) sb.append(elementsInfix); 96 | sb.append(k).append(kvInfix).append(get(k)); 97 | was = true; 98 | } 99 | return sb.toString(); 100 | } 101 | 102 | default String toString(String elementsInfix, BiFunction toStringFunction) { 103 | boolean was = false; 104 | StringBuilder sb = new StringBuilder(""); 105 | for (K k : keySet()) { 106 | if (was) sb.append(elementsInfix); 107 | sb.append(toStringFunction.apply(k, get(k))); 108 | was = true; 109 | } 110 | return sb.toString(); 111 | } 112 | 113 | default YMap assertSize(int s) { 114 | if (size() != s) throw new RuntimeException("Expected size " + s + " but was " + size()); 115 | return this; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YCollectionWrapper.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.Iterator; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | 9 | import static yk.jcommon.collections.YArrayList.al; 10 | 11 | public class YCollectionWrapper implements YCollection { 12 | private Collection collection; 13 | 14 | @Override 15 | public YCollection emptyInstance() { 16 | throw new RuntimeException("Not implemented"); 17 | } 18 | 19 | public YCollectionWrapper(Collection collection) { 20 | this.collection = collection; 21 | } 22 | 23 | @Override 24 | public YList filter(Predicate predicate) { 25 | YList result = al(); 26 | for (T t : this) if (predicate.test(t)) result.add(t); 27 | return result; 28 | } 29 | 30 | @Override 31 | public YList map(Function mapper) { 32 | YList result = al(); 33 | for (T t : this) result.add(mapper.apply(t)); 34 | return result; 35 | } 36 | 37 | @Override 38 | public YCollection flatMap(Function> mapper) { 39 | YArrayList result = al(); 40 | for (T t : this) for (R r : mapper.apply(t)) result.add(r); 41 | return result; 42 | } 43 | 44 | @Override 45 | public YList cdr() { 46 | YList result = al(); 47 | Iterator iterator = this.iterator(); 48 | iterator.next(); 49 | for (; iterator.hasNext(); ) result.add(iterator.next()); 50 | return result; 51 | } 52 | 53 | @Override 54 | public YList withAll(Collection c) { 55 | YList result = al(); 56 | result.addAll(this); 57 | result.addAll(c); 58 | return result; 59 | } 60 | 61 | @Override 62 | public YList with(T t) { 63 | YList result = al(); 64 | result.addAll(this); 65 | result.add(t); 66 | return result; 67 | } 68 | 69 | @Override 70 | public YCollection with(T... tt) { 71 | YList result = al(); 72 | result.addAll(this); 73 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 74 | return result; 75 | } 76 | 77 | @Override 78 | public YList withoutAll(Collection c) { 79 | YList result = al(); 80 | for (T t : this) if (!c.contains(t)) result.add(t); 81 | return result; 82 | } 83 | 84 | @Override 85 | public YList without(T t) { 86 | YList result = al(); 87 | for (T tt : this) if (tt != t) result.add(tt); 88 | return result; 89 | } 90 | 91 | @SafeVarargs 92 | @Override 93 | public final YList without(T... tt) { 94 | return withoutAll(Arrays.asList(tt)); 95 | } 96 | 97 | @Override 98 | public YList take(int count) { 99 | YList result = al(); 100 | Iterator it = iterator(); 101 | for (int i = 0; i < count && it.hasNext(); i++) result.add(it.next()); 102 | return result; 103 | } 104 | 105 | @Override 106 | public int size() { 107 | return collection.size(); 108 | } 109 | 110 | @Override 111 | public boolean isEmpty() { 112 | return collection.isEmpty(); 113 | } 114 | 115 | @Override 116 | public boolean contains(Object o) { 117 | return collection.contains(o); 118 | } 119 | 120 | @Override 121 | public Iterator iterator() { 122 | return collection.iterator(); 123 | } 124 | 125 | @Override 126 | public Object[] toArray() { 127 | return collection.toArray(); 128 | } 129 | 130 | @Override 131 | public T1[] toArray(T1[] a) { 132 | return collection.toArray(a); 133 | } 134 | 135 | @Override 136 | public boolean add(T t) { 137 | return add(t); 138 | } 139 | 140 | @Override 141 | public boolean remove(Object o) { 142 | return collection.remove(o); 143 | } 144 | 145 | @Override 146 | public boolean containsAll(Collection c) { 147 | return collection.containsAll(c); 148 | } 149 | 150 | @Override 151 | public boolean addAll(Collection c) { 152 | return collection.addAll(c); 153 | } 154 | 155 | @Override 156 | public boolean removeAll(Collection c) { 157 | return collection.removeAll(c); 158 | } 159 | 160 | @Override 161 | public boolean retainAll(Collection c) { 162 | return collection.retainAll(c); 163 | } 164 | 165 | @Override 166 | public void clear() { 167 | collection.clear(); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MIGRATED to [ycollections](https://github.com/kravchik/ycollections) 2 | 3 | # jcommon 4 | 5 | _Let's say we want to filter a Map, and we have two options..._ 6 | 7 | Option 1: 8 | ``` 9 | sMap = sMap.entrySet().stream() 10 | .filter(e -> e.getKey().startsWith("a")) 11 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 12 | ``` 13 | 14 | Option 2: 15 | ``` 16 | yMap = yMap.filter((k, v) -> k.startsWith("a")); 17 | ``` 18 | 19 | If you'd prefer Option 2, you are welcome to continue reading. 20 | 21 | 22 | streams are ok if you have many steps, but bad for simple steps (and simple steps are more often) 23 | instantiation (vs standard, vs Collections, vs Guava) 24 | everything extends usual collections (so accepted everywhere) 25 | everything is modifiable except of added methods 26 | examples of creating, filtering, mapping, sorting 27 | maps and sets are sorted (pros) 28 | ycollectiona are copying every time but... 29 | 30 | 31 | Common utils, abstractions, and tools that I use in my projects. They make Java pleasant. 32 | 33 | _There was more code here but it has been moved to [yincubator](https://github.com/kravchik/yincubator)_ 34 | 35 | _Now, without apache commons dependency!_ 36 | 37 | **How to MAKE JAVA GREAT AGAIN?** 38 | 1. don't use streams or guava 39 | 2. use YCollections 40 | 3. if (IF) your profiler says you to - then refactor an algorithm with YCollections into ugly but efficient empiric code (fors, side-effects, etc) 41 | 42 | They are just extensions of the standard collections - you can use YList everywhere where you use List. Same goes for YArrayList, YSet, YMap, etc. 43 | 44 | YCollections will suffice in most cases: 45 | 1. 99.9% of an enterprise project 46 | 1. 80% of a game-dev project 47 | 1. 100% of scripts 48 | 1. 100% of tests 49 | 50 | It is better to stick with simple and elegant YCollections and optimize small percentage of places, than to suffer (even if you don't know it yet) with streams, and guava (I even not talking about standard collections initialization). 51 | 52 | _Why streams are bad?_ 53 | 1. `stream()` and `collect` parts. In YCollections you don't need to collect. Though you too have to convert usual collection or array into YCollection (`toYList(someList)`, `al(someArray)`). _You can't imagine how nicer your scripts will look!_ 54 | 2. verbosity 55 | 3. you can't ask them to add something (me, you can ask) 56 | 4. premature optimization, complex insides, etc. 57 | 58 | _Why Guava is bad?_ 59 | 1. `ImmutableList.of` - you can't static import that. In YCollections you just use `al()` or `hm()` (static import from `YArrayList.al()` and `YHashMap.hm()`) Which leads to elegant and concise code. _You can't imagine how nicer your tests will look!_ 60 | 61 | 62 | ## YCollections 63 | **yk.jcommon.collections** 64 | 65 | Collections as they should be. 66 | 67 | Example 1 68 | ```java 69 | String names = al(new File("/home/user/").listFiles()) 70 | .filter(File::isDirectory) //only dirs 71 | .map(File::getName) //get name 72 | .filter(n -> n.startsWith(".")) //only invisible 73 | .sorted() //sorted 74 | .toString(", "); //to print fine 75 | System.out.println(names); 76 | ``` 77 | Example 2 78 | ```java 79 | YList all = al("shift", "ctrl", "alt", "super"); 80 | System.out.println(all.eachToEach(all) //take pares of each to each 81 | .map(p -> p //rework each pare 82 | .toSet() // convert to set to remove "alt alt" and similar 83 | .sorted() // sort (yes, it is a LinkedHashSet inside) 84 | .toString(", ") // make a string 85 | ) 86 | .toSet() //convert to set to remove duplicates ("alt shift", "shift alt") 87 | .sorted() //sort 88 | .toString("\n")); //make a result string 89 | ``` 90 | Gives result: 91 | ``` 92 | alt 93 | alt, ctrl 94 | alt, shift 95 | alt, super 96 | ctrl 97 | ctrl, shift 98 | ctrl, super 99 | shift 100 | shift, super 101 | super 102 | ``` 103 | 104 | * each collection extends standard java collection, so you can use it whenever standard collection would else be used 105 | * just added some functional not modifying methods 106 | * yes, there are copies everywhere, but hey! Optimize it when your profiler says you so! 107 | * very convenient 108 | * resulting code is looking like Xtend's or Scala's but with pure java 109 | * java8's .stream() I consider not usable 110 | 111 | ## mvn artifact 112 | 113 | ```xml 114 | 115 | yk 116 | https://github.com/kravchik/mvn-repo/raw/master 117 | 118 | 119 | 120 | yk 121 | jcommon 122 | 0.122 123 | 124 | ``` 125 | (current dev version is 0.123-SNAPSHOT) 126 | 127 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YCollections.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.*; 4 | import java.util.function.BiFunction; 5 | import java.util.function.Function; 6 | import java.util.function.Predicate; 7 | 8 | import static yk.jcommon.collections.YArrayList.al; 9 | import static yk.jcommon.collections.YArrayList.toYList; 10 | 11 | /** 12 | * Created with IntelliJ IDEA. 13 | * User: yuri 14 | * Date: 8/12/14 15 | * Time: 5:48 PM 16 | */ 17 | public class YCollections { 18 | public static YArrayList filterList(List l, Predicate predicate) { 19 | YArrayList result = new YArrayList(); 20 | for (int i = 0, lSize = l.size(); i < lSize; i++) { 21 | T t = l.get(i); 22 | if (predicate.test(t)) result.add(t); 23 | } 24 | return result; 25 | } 26 | 27 | public static YHashSet filterSet(Collection l, Predicate predicate) { 28 | YHashSet result = new YHashSet(); 29 | for (T t : l) if (predicate.test(t)) result.add(t); 30 | return result; 31 | } 32 | 33 | static YArrayList mapList(List source, Function mapper) { 34 | YArrayList result = new YArrayList(); 35 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 36 | result.add(mapper.apply(source.get(i))); 37 | } 38 | return result; 39 | } 40 | 41 | static YSet mapSet(Set source, Function mapper) { 42 | YHashSet result = new YHashSet(); 43 | for (T t : source) result.add(mapper.apply(t)); 44 | return result; 45 | } 46 | 47 | static YArrayList flatMapList(List source, Function> mapper) { 48 | YArrayList result = new YArrayList(); 49 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 50 | for (R r : mapper.apply(source.get(i))) result.add(r); 51 | } 52 | return result; 53 | } 54 | 55 | static YHashSet flatMapSet(Set source, Function> mapper) { 56 | YHashSet result = new YHashSet(); 57 | for (T t : source) { 58 | for (R r : mapper.apply(t)) result.add(r); 59 | } 60 | return result; 61 | } 62 | 63 | static YList sortedCollection(Collection source) { 64 | YList result = toYList(source); 65 | Collections.sort((List)result); 66 | return result; 67 | } 68 | 69 | static YList sortedCollection(Collection source, Comparator comparator) { 70 | YList result = toYList(source); 71 | Collections.sort(result, comparator); 72 | return result; 73 | } 74 | 75 | static T maxFromList(List source) { 76 | if (source.isEmpty()) throw new RuntimeException("can't get max on empty collection"); 77 | T result = null; 78 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 79 | T t = source.get(i); 80 | if (result == null || ((Comparable)t).compareTo(result) > 0) result = t; 81 | } 82 | 83 | return result; 84 | } 85 | 86 | static T maxFromList(List source, Comparator comparator) { 87 | if (source.isEmpty()) throw new RuntimeException("can't get max on empty collection"); 88 | T result = null; 89 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 90 | T t = source.get(i); 91 | if (result == null || comparator.compare(t, result) > 0) result = t; 92 | } 93 | 94 | return result; 95 | } 96 | 97 | static T maxFromCollection(Collection source, Comparator comparator) { 98 | if (source.isEmpty()) throw new RuntimeException("can't get max on empty collection"); 99 | T result = null; 100 | for (T t : source) { 101 | if (result == null || comparator.compare(t, result) > 0) result = t; 102 | } 103 | return result; 104 | } 105 | 106 | static T minFromList(List source, Comparator comparator) { 107 | if (source.isEmpty()) throw new RuntimeException("can't get max on empty collection"); 108 | T result = null; 109 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 110 | T t = source.get(i); 111 | if (result == null || comparator.compare(t, result) < 0) result = t; 112 | } 113 | 114 | return result; 115 | } 116 | 117 | static T minFromCollection(Collection source, Comparator comparator) { 118 | if (source.isEmpty()) throw new RuntimeException("can't get min on empty collection"); 119 | T result = null; 120 | for (T t : source) { 121 | if (result == null || comparator.compare(t, result) < 0) result = t; 122 | } 123 | return result; 124 | } 125 | 126 | static T maxFromCollection(Collection source) { 127 | if (source.isEmpty()) throw new RuntimeException("can't get max on empty collection"); 128 | T result = null; 129 | for (T t : source) if (result == null || ((Comparable)t).compareTo(result) > 0) result = t; 130 | return result; 131 | } 132 | 133 | static T minFromList(List source) { 134 | if (source.isEmpty()) throw new RuntimeException("can't get min on empty collection"); 135 | T result = null; 136 | for (int i = 0, sourceSize = source.size(); i < sourceSize; i++) { 137 | T t = source.get(i); 138 | if (result == null || ((Comparable)t).compareTo(result) < 0) result = t; 139 | } 140 | 141 | return result; 142 | } 143 | 144 | static T minFromCollection(Collection source) { 145 | if (source.isEmpty()) throw new RuntimeException("can't get min on empty collection"); 146 | T result = null; 147 | for (T t : source) if (result == null || ((Comparable)t).compareTo(result) < 0) result = t; 148 | return result; 149 | } 150 | 151 | public static YArrayList cdr(List source) { 152 | YArrayList result = new YArrayList(); 153 | for (int i = 1, sourceSize = source.size(); i < sourceSize; i++) { 154 | result.add(source.get(i)); 155 | } 156 | return result; 157 | } 158 | 159 | static YArrayList subListFromList(List source, int fromIndex, int toIndex) { 160 | YArrayList result = YArrayList.al(); 161 | for (int i = fromIndex; i < toIndex; i++) result.add(source.get(i)); 162 | return result; 163 | } 164 | 165 | public static YArrayList eachToEach(Collection aa, Collection bb, BiFunction combinator) { 166 | YArrayList result = new YArrayList<>(); 167 | for (A a : aa) { 168 | for (B b : bb) { 169 | result.add(combinator.apply(a, b)); 170 | } 171 | } 172 | return result; 173 | } 174 | 175 | public static YSet subSet(Collection c, T t) { 176 | YHashSet result = new YHashSet<>(); 177 | for (T t1 : c) if (!t1.equals(t)) result.add(t1); 178 | return result; 179 | } 180 | 181 | public static YSet subSet(Collection c, Collection t) { 182 | YHashSet result = new YHashSet<>(); 183 | for (T t1 : c) if (!t.contains(t1)) result.add(t1); 184 | return result; 185 | } 186 | 187 | public static YSet appendSet(Collection ts, Collection tt) { 188 | YHashSet result = new YHashSet<>(); 189 | result.addAll(ts); 190 | result.addAll(tt); 191 | return result; 192 | } 193 | 194 | public static YSet appendSet(Collection ts, T t) { 195 | YHashSet result = new YHashSet<>(); 196 | result.addAll(ts); 197 | result.add(t); 198 | return result; 199 | } 200 | 201 | public static YSet> scramble(YSet aa, YSet bb) { 202 | return scramble(aa, bb, YHashMap.hm()); 203 | } 204 | 205 | public static YSet> scramble(YSet aa, YSet bb, YMap prev) { 206 | if (aa.isEmpty() || bb.isEmpty()) return YHashSet.hs(prev); 207 | YSet> result = YHashSet.hs(); 208 | T car = aa.car(); 209 | YSet cdr = aa.cdr(); 210 | for (T b : bb) result.addAll(scramble(cdr, bb.without(b), prev.with(car, b))); 211 | return result; 212 | } 213 | 214 | public static YList zip(YList a, YList b, BiFunction f) { 215 | YList result = al(); 216 | for (int i = 0; i < a.size(); i++) { 217 | if (b.size() <= i) break; 218 | result.add(f.apply(a.get(i), b.get(i))); 219 | } 220 | return result; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YList.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Comparator; 5 | import java.util.List; 6 | import java.util.function.*; 7 | 8 | 9 | /** 10 | * Created with IntelliJ IDEA. 11 | * User: yuri 12 | * Date: 8/12/14 13 | * Time: 3:27 PM 14 | */ 15 | //TODO remove defaults which return modifiable list 16 | @SuppressWarnings("ForLoopReplaceableByForEach") 17 | public interface YList extends YCollection, List { 18 | //TODO nTimes 19 | 20 | @Override//TODO remove (currently needed for cs translator) 21 | T get(int index); 22 | 23 | default T getOr(int index, T or) { 24 | return index >= size() || index < 0 ? or : get(index); 25 | } 26 | 27 | @Override 28 | YList filter(Predicate predicate); 29 | 30 | @Override 31 | YList map(Function mapper); 32 | 33 | @Override 34 | default YList mapWithIndex(BiFunction mapper) { 35 | return (YList) YCollection.super.mapWithIndex(mapper); 36 | } 37 | 38 | @Override 39 | YList flatMap(Function> mapper); 40 | 41 | /** 42 | * The same as 'forEach', but returns 'this' so can continue using the instasnce. 43 | */ 44 | @Override 45 | default YList forEachFun(Consumer consumer) { 46 | for (T t : this) consumer.accept(t); 47 | return this; 48 | } 49 | 50 | default YList forZip(YList b, BiConsumer f) { 51 | if (size() != b.size()) throw new RuntimeException("Expected the same size"); 52 | for (int i = 0; i < this.size(); i++) f.accept(this.get(i), b.get(i)); 53 | return this; 54 | } 55 | 56 | @Override 57 | default YList forWithIndex(BiConsumer consumer) { 58 | for (int i = 0; i < size(); i++) consumer.accept(i, get(i)); 59 | return this; 60 | } 61 | 62 | @Override 63 | default T cadr() { 64 | return get(1); 65 | } 66 | 67 | @Override 68 | default YList toList() { 69 | return this; 70 | } 71 | 72 | 73 | @Override 74 | YList cdr(); 75 | @Override 76 | YList withAll(Collection c); 77 | @Override 78 | YList with(T t); 79 | YList withAt(int index, T t); 80 | @Override 81 | @SuppressWarnings("unchecked") 82 | YList with(T... t); 83 | @Override 84 | YList withoutAll(Collection c); 85 | @Override 86 | YList without(T t); 87 | @Override 88 | @SuppressWarnings("unchecked") 89 | YList without(T... t); 90 | @Override 91 | YList take(int count); 92 | 93 | @Override 94 | YList subList(int fromIndex, int toIndex); 95 | T last(); 96 | 97 | default T lastOr(T t) { 98 | if (isEmpty()) return t; 99 | return last(); 100 | } 101 | 102 | default T lastOrCalc(Supplier supplier) { 103 | if (isEmpty()) return supplier.get(); 104 | return last(); 105 | } 106 | 107 | YList allMin(Comparator comparator); 108 | 109 | YList> eachToEach(YList other); 110 | 111 | YList eachToEach(Collection other, BiFunction combinator); 112 | 113 | YList eachToEach(List other, BiFunction combinator); 114 | 115 | default void forUniquePares(BiConsumer bc) { 116 | for (int i = 0; i < size()-1; i++) for (int j = i+1; j < size(); j++) bc.accept(get(i), get(j)); 117 | } 118 | 119 | YList mapUniquePares(BiFunction bf); 120 | 121 | default YList> split(Object eq) { 122 | return split(e -> e == null ? eq == null : e.equals(eq)); 123 | } 124 | 125 | YList> split(Predicate isSplitter); 126 | 127 | YList reverse(); 128 | 129 | default void forEachNeighbours(BiConsumer consumer) { 130 | for (int i = 0; i < this.size(); i++) { 131 | T t1 = this.get((i + 0) % this.size()); 132 | T t2 = this.get((i + 1) % this.size()); 133 | consumer.accept(t1, t2); 134 | } 135 | } 136 | 137 | default void forEachNeighbours(Consumer3 consumer) { 138 | for (int i = 0; i < this.size(); i++) { 139 | T t1 = this.get((i + 0) % this.size()); 140 | T t2 = this.get((i + 1) % this.size()); 141 | T t3 = this.get((i + 2) % this.size()); 142 | consumer.accept(t1, t2, t3); 143 | } 144 | } 145 | 146 | default void forEachNeighbours(Consumer4 consumer) { 147 | for (int i = 0; i < this.size(); i++) { 148 | T t1 = this.get((i + 0) % this.size()); 149 | T t2 = this.get((i + 1) % this.size()); 150 | T t3 = this.get((i + 2) % this.size()); 151 | T t4 = this.get((i + 3) % this.size()); 152 | consumer.accept(t1, t2, t3, t4); 153 | } 154 | } 155 | 156 | @Override 157 | default T last(Predicate predicate) { 158 | T result = null; 159 | for (int i = 0, thisSize = this.size(); i < thisSize; i++) { 160 | T t = this.get(i); 161 | if (predicate.test(t)) result = t; 162 | } 163 | return result; 164 | } 165 | 166 | @Override 167 | default > T max(Function evaluator) { 168 | if (isEmpty()) throw new RuntimeException("can't get max on empty collection"); 169 | T max = null; 170 | CMP maxComparable = null; 171 | for (int i = 0; i < this.size(); i++) { 172 | T t = this.get(i); 173 | CMP nextComparable = evaluator.apply(t); 174 | if (nextComparable == null) throw new RuntimeException("evaluator shouldn't return null values"); 175 | if (maxComparable == null || maxComparable.compareTo(nextComparable) < 0) { 176 | max = t; 177 | maxComparable = nextComparable; 178 | } 179 | } 180 | return max; 181 | } 182 | 183 | @Override 184 | default T maxByFloat(Function_float_T evaluator) { 185 | if (isEmpty()) throw new RuntimeException("can't get max on empty collection"); 186 | T max = null; 187 | float maxComparable = 0; 188 | boolean found = false; 189 | for (int i = 0; i < this.size(); i++) { 190 | T t = this.get(i); 191 | float nextComparable = evaluator.apply(t); 192 | if (!found || nextComparable > maxComparable) { 193 | max = t; 194 | maxComparable = nextComparable; 195 | } 196 | found = true; 197 | } 198 | return max; 199 | } 200 | 201 | @Override 202 | default > T min(Function evaluator) { 203 | if (isEmpty()) throw new RuntimeException("can't get min on empty collection"); 204 | T min = null; 205 | CMP minComparable = null; 206 | for (int i = 0; i < this.size(); i++) { 207 | T t = this.get(i); 208 | CMP nextComparable = evaluator.apply(t); 209 | if (nextComparable == null) throw new RuntimeException("evaluator shouldn't return null values"); 210 | if (minComparable == null || minComparable.compareTo(nextComparable) >= 0) { 211 | min = t; 212 | minComparable = nextComparable; 213 | } 214 | } 215 | return min; 216 | } 217 | 218 | @Override 219 | default T minByFloat(Function_float_T evaluator) { 220 | if (isEmpty()) throw new RuntimeException("can't get min on empty collection"); 221 | T min = null; 222 | float minComparable = 0; 223 | boolean found = false; 224 | for (int i = 0; i < this.size(); i++) { 225 | T t = this.get(i); 226 | float nextComparable = evaluator.apply(t); 227 | if (!found || nextComparable < minComparable) { 228 | min = t; 229 | minComparable = nextComparable; 230 | } 231 | found = true; 232 | } 233 | return min; 234 | } 235 | 236 | default YList zipWith(YList b, BiFunction f) { 237 | return YCollections.zip(this, b, f); 238 | } 239 | 240 | @Override 241 | default YList assertSize(int s) { 242 | if (size() != s) throw new RuntimeException("Expected size " + s + " but was " + size()); 243 | return this; 244 | } 245 | 246 | default YList forThis(YListConsumer c) { 247 | c.accept(this); 248 | return this; 249 | } 250 | 251 | default T2 mapThis(YListFunction f) { 252 | return f.apply(this); 253 | } 254 | 255 | interface YListConsumer { 256 | void accept(YList al); 257 | } 258 | 259 | interface YListFunction { 260 | T2 apply(YList al); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YHashMap.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.*; 4 | import java.util.function.BiFunction; 5 | import java.util.function.BiPredicate; 6 | import java.util.function.Function; 7 | 8 | import static yk.jcommon.collections.YArrayList.al; 9 | import static yk.jcommon.collections.YArrayList.toYList; 10 | 11 | /** 12 | * Created with IntelliJ IDEA. 13 | * User: yuri 14 | * Date: 10/1/14 15 | * Time: 11:50 PM 16 | */ 17 | public class YHashMap extends LinkedHashMap implements YMap { 18 | public YHashMap() { 19 | } 20 | 21 | public YHashMap(Map m) { 22 | super(m); 23 | } 24 | 25 | public static YHashMap hm(K k, V v, Object... oo) { 26 | YHashMap result = new YHashMap(); 27 | result.put(k, v); 28 | for (int i = 0; i < oo.length; i += 2) result.put(oo[i], oo[i + 1]); 29 | return result; 30 | } 31 | 32 | public static YHashMap toYMap(Map source) { 33 | YHashMap result = new YHashMap(); 34 | result.putAll(source); 35 | return result; 36 | } 37 | 38 | public static YHashMap hm() { 39 | return new YHashMap<>(); 40 | } 41 | 42 | @Override 43 | public YMap filter(BiPredicate predicate) { 44 | YMap result = hm(); 45 | for (Map.Entry entry : this.entrySet()) 46 | if (predicate.test(entry.getKey(), entry.getValue())) result.put(entry.getKey(), entry.getValue()); 47 | return result; 48 | } 49 | 50 | @Override 51 | public YList mapToList(BiFunction mapper) { 52 | YList result = al(); 53 | for (Map.Entry entry : this.entrySet()) { 54 | result.add(mapper.apply(entry.getKey(), entry.getValue())); 55 | } 56 | return result; 57 | } 58 | 59 | @Override 60 | public YMap map(Function keyMapper, Function valueMapper) { 61 | YMap result = hm(); 62 | for (Map.Entry entry : this.entrySet()) { 63 | result.put(keyMapper.apply(entry.getKey()), valueMapper.apply(entry.getValue())); 64 | } 65 | return result; 66 | } 67 | 68 | @Override 69 | public YMap map(BiFunction keyMapper, BiFunction valueMapper) { 70 | YMap result = hm(); 71 | for (Map.Entry entry : this.entrySet()) { 72 | result.put(keyMapper.apply(entry.getKey(), entry.getValue()), valueMapper.apply(entry.getKey(), entry.getValue())); 73 | } 74 | return result; 75 | } 76 | 77 | @Override 78 | public Tuple car() { 79 | if (isEmpty()) return null; 80 | Map.Entry next = entrySet().iterator().next(); 81 | return new Tuple<>(next.getKey(), next.getValue()); 82 | } 83 | 84 | @Override 85 | public YMap cdr() { 86 | return without(car().a); 87 | } 88 | 89 | @Override 90 | public Tuple first() { 91 | return car(); 92 | } 93 | 94 | @Override 95 | public Tuple last() { 96 | K key = null; 97 | for (K k : keySet()) key = k; 98 | return key == null ? null : new Tuple(key, get(key)); 99 | } 100 | 101 | //TODO test 102 | @Override 103 | public Tuple max(BiFunction evaluator) { 104 | float maxValue = Float.NEGATIVE_INFINITY; 105 | K maxKey = null; 106 | for (K k : super.keySet()) { 107 | float curValue = evaluator.apply(k, get(k)); 108 | if (curValue > maxValue) { 109 | maxKey = k; 110 | maxValue = curValue; 111 | } 112 | } 113 | return new Tuple<>(maxKey, get(maxKey)); 114 | } 115 | 116 | //TODO test 117 | @Override 118 | public V maxValue(Function evaluator) { 119 | float maxValue = Float.NEGATIVE_INFINITY; 120 | V mv = null; 121 | for (V v : super.values()) { 122 | float curValue = evaluator.apply(v); 123 | if (curValue > maxValue) { 124 | mv = v; 125 | maxValue = curValue; 126 | } 127 | } 128 | return mv; 129 | } 130 | 131 | //TODO test 132 | @Override 133 | public Tuple min(BiFunction evaluator) { 134 | float minValue = Float.MAX_VALUE; 135 | K minKey = null; 136 | for (K k : super.keySet()) { 137 | float curValue = evaluator.apply(k, get(k)); 138 | if (curValue < minValue) { 139 | minKey = k; 140 | minValue = curValue; 141 | } 142 | } 143 | return new Tuple<>(minKey, get(minKey)); 144 | } 145 | 146 | //TODO test 147 | @Override 148 | public V minValue(Function evaluator) { 149 | float minValue = Float.MAX_VALUE; 150 | V mv = null; 151 | for (V v : super.values()) { 152 | float curValue = evaluator.apply(v); 153 | if (curValue < minValue) { 154 | mv = v; 155 | minValue = curValue; 156 | } 157 | } 158 | return mv; 159 | } 160 | 161 | //TODO test 162 | @Override 163 | public boolean isAll(BiPredicate predicate) { 164 | for (Map.Entry entry : super.entrySet()) if (!predicate.test(entry.getKey(), entry.getValue())) return false; 165 | return true; 166 | } 167 | 168 | //TODO test 169 | @Override 170 | public boolean isAny(BiPredicate predicate) { 171 | for (Map.Entry entry : super.entrySet()) if (predicate.test(entry.getKey(), entry.getValue())) return true; 172 | return false; 173 | } 174 | 175 | //TODO test 176 | @Override 177 | public V getOr(K key, V cur) { 178 | V result = get(key); 179 | return result == null ? cur : result; 180 | } 181 | 182 | @Override 183 | public YSet keySet() { 184 | return new YHashSetWrapper<>(super.keySet()); 185 | } 186 | 187 | @Override 188 | public YCollection values() { 189 | return new YCollectionWrapper<>(super.values()); 190 | } 191 | 192 | //TODO test 193 | @Override 194 | public YMap with(K k, V v) { 195 | YMap result = hm(); 196 | result.putAll(this); 197 | result.put(k, v); 198 | return result; 199 | } 200 | 201 | //TODO test 202 | @Override 203 | public YMap with(K k, V v, Object... other) { 204 | YMap result = hm(); 205 | result.putAll(this); 206 | result.putAll(k, v, other); 207 | return result; 208 | } 209 | 210 | //TODO test 211 | @Override 212 | public YMap with(Map kv) { 213 | YMap result = hm(); 214 | result.putAll(this); 215 | result.putAll(kv); 216 | return result; 217 | } 218 | 219 | //TODO test 220 | @Override 221 | public YMap without(K pKey) { 222 | YMap result = new YHashMap<>(); 223 | result.putAll(this); 224 | result.remove(pKey); 225 | return result; 226 | } 227 | 228 | //TODO test 229 | @Override 230 | public YMap without(Collection keys) { 231 | YMap result = toYMap(this); 232 | for (K key : keys) result.remove(key); 233 | return result; 234 | } 235 | 236 | //TODO test 237 | @Override 238 | public YMap sorted(Comparator> comparator) { 239 | YMap result = hm(); 240 | for (Map.Entry entry : toYList(this.entrySet()).sorted(comparator)) result.put(entry.getKey(), entry.getValue()); 241 | return result; 242 | } 243 | 244 | //TODO test 245 | @Override 246 | public YMap sortedBy(BiFunction evaluator) { 247 | List> temp = al(); 248 | for (Map.Entry entry : this.entrySet()) temp.add(new Temp<>(entry, evaluator)); 249 | Collections.sort(temp); 250 | YMap result = hm(); 251 | for (Temp t : temp) result.put(t.entry.getKey(), t.entry.getValue()); 252 | return result; 253 | } 254 | 255 | //TODO test 256 | @Override 257 | public YMap take(int n) { 258 | YMap result = hm(); 259 | int count = 0; 260 | for (K k : keySet()) { 261 | if (count++ >= n) break; 262 | result.put(k, get(k)); 263 | } 264 | return result; 265 | } 266 | 267 | private static class Temp implements Comparable> { 268 | Comparable evaluation; 269 | Map.Entry entry; 270 | 271 | private Temp(Map.Entry entry, BiFunction evaluator) { 272 | this.entry = entry; 273 | evaluation = evaluator.apply(entry.getKey(), entry.getValue()); 274 | } 275 | 276 | @Override 277 | public int compareTo(Temp o) { 278 | return evaluation.compareTo(o.evaluation); 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YArrayList.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.*; 4 | import java.util.function.BiFunction; 5 | import java.util.function.Function; 6 | import java.util.function.Predicate; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: yuri 11 | * Date: 8/12/14 12 | * Time: 3:26 PM 13 | * 14 | * TODO remove. YList should cover everything 15 | */ 16 | public class YArrayList extends ArrayList implements YList { 17 | @Override 18 | public YCollection emptyInstance() { 19 | return al(); 20 | } 21 | 22 | @Override 23 | public boolean isAny(Predicate predicate) { 24 | for (int i = 0, thisSize = this.size(); i < thisSize; i++) { 25 | if (predicate.test(this.get(i))) return true; 26 | } 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isAll(Predicate predicate) { 32 | for (int i = 0, thisSize = this.size(); i < thisSize; i++) { 33 | if (!predicate.test(this.get(i))) return false; 34 | } 35 | return true; 36 | } 37 | 38 | public YArrayList() { 39 | } 40 | 41 | public YArrayList(Collection c) { 42 | super(c); 43 | } 44 | 45 | //TODO test 46 | public static YArrayList toYList(Collection source) { 47 | YArrayList result = new YArrayList<>(); 48 | result.addAll(source); 49 | return result; 50 | } 51 | 52 | //TODO test 53 | @SafeVarargs 54 | public static YArrayList al(T... tt) { 55 | YArrayList result = new YArrayList<>(); 56 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 57 | return result; 58 | } 59 | 60 | public static YArrayList al() {//to avoid creation of empty array if calling al(T... tt) 61 | return new YArrayList<>(); 62 | } 63 | 64 | public static YArrayList allocate(int size) { 65 | YArrayList result = al(); 66 | for (int i = 0; i < size; i++) result.add(null); 67 | return result; 68 | } 69 | 70 | public static YArrayList allocate(int size, Function_T_int gen) { 71 | YArrayList result = al(); 72 | for (int i = 0; i < size; i++) result.add(gen.apply(i)); 73 | return result; 74 | } 75 | 76 | public static YArrayList times(int n, Function_T_int generator) { 77 | YArrayList result = new YArrayList<>(); 78 | for (int i = 0; i < n; i++) result.add(generator.apply(i)); 79 | return result; 80 | } 81 | 82 | //TODO test 83 | @Override 84 | public YArrayList filter(Predicate predicate) { 85 | return YCollections.filterList(this, predicate); 86 | } 87 | 88 | //TODO test 89 | @Override 90 | public YArrayList map(Function mapper) { 91 | return YCollections.mapList(this, mapper); 92 | } 93 | 94 | //TODO test 95 | @Override 96 | public YArrayList flatMap(Function> mapper) { 97 | return YCollections.flatMapList(this, mapper); 98 | } 99 | 100 | @Override 101 | public R reduce(R first, BiFunction folder) { 102 | R result = first; 103 | for (int i = 0; i < size(); i++) result = folder.apply(result, get(i)); 104 | return result; 105 | } 106 | 107 | @Override 108 | public T max() { 109 | return YCollections.maxFromList(this); 110 | } 111 | 112 | @Override 113 | public T max(Comparator comparator) { 114 | return YCollections.maxFromList(this, comparator); 115 | } 116 | 117 | @Override 118 | public T min() { 119 | return YCollections.minFromList(this); 120 | } 121 | 122 | @Override 123 | public T min(Comparator comparator) { 124 | return YCollections.minFromList(this, comparator); 125 | } 126 | 127 | //TODO test 128 | @Override 129 | public YArrayList allMin(Comparator comparator) { 130 | if (isEmpty()) return this; 131 | YArrayList result = al(); 132 | T cur = null; 133 | for (T t : sorted(comparator)) { 134 | if (cur == null || comparator.compare(cur, t) == 0) { 135 | cur = t; 136 | result.add(t); 137 | } else { 138 | break; 139 | } 140 | } 141 | return result; 142 | } 143 | 144 | //TODO test 145 | @Override 146 | public T car() { 147 | return get(0); 148 | } 149 | 150 | //TODO test 151 | @Override 152 | public YArrayList cdr() { 153 | return YCollections.cdr(this); 154 | } 155 | 156 | @Override 157 | public T last() { 158 | return get(size() - 1); 159 | } 160 | 161 | //TODO test 162 | @SuppressWarnings("NullableProblems") 163 | @Override 164 | public YArrayList subList(int fromIndex, int toIndex) { 165 | return YCollections.subListFromList(this, fromIndex, toIndex); 166 | } 167 | 168 | //TODO test 169 | @Override 170 | public YArrayList withAll(Collection c) { 171 | YArrayList result = al(); 172 | result.addAll(this); 173 | result.addAll(c); 174 | return result; 175 | } 176 | 177 | //TODO test 178 | @Override 179 | public YArrayList with(T t) { 180 | YArrayList result = al(); 181 | result.addAll(this); 182 | result.add(t); 183 | return result; 184 | } 185 | 186 | @Override 187 | public YArrayList withAt(int index, T t) { 188 | YArrayList result = toYList(this); 189 | result.set(index, t); 190 | return result; 191 | } 192 | 193 | //TODO test 194 | @SafeVarargs 195 | @Override 196 | public final YArrayList with(T... tt) { 197 | YArrayList result = al(); 198 | result.addAll(this); 199 | for (int i = 0; i < tt.length; i++) result.add(tt[i]); 200 | return result; 201 | } 202 | 203 | //TODO test 204 | @Override 205 | public YArrayList withoutAll(Collection c) { 206 | YArrayList result = al(); 207 | for (T t : this) if (!c.contains(t)) result.add(t); 208 | return result; 209 | } 210 | 211 | //TODO test 212 | @Override 213 | public YArrayList without(T t) { 214 | YArrayList result = al(); 215 | for (T tt : this) if (tt != t) result.add(tt); 216 | return result; 217 | } 218 | 219 | //TODO test 220 | @SafeVarargs 221 | @Override 222 | public final YArrayList without(T... tt) { 223 | return withoutAll(Arrays.asList(tt)); 224 | } 225 | 226 | //TODO test 227 | @Override 228 | public YArrayList take(int count) { 229 | YArrayList result = al(); 230 | for (int i = 0; i < count; i++) { 231 | if (i >= size()) break; 232 | result.add(get(i)); 233 | } 234 | return result; 235 | } 236 | 237 | @Override 238 | public YList> eachToEach(YList other) { 239 | YList> result = al(); 240 | for (T t : this) for (T o : other) result.add(al(t, o)); 241 | return result; 242 | } 243 | 244 | @Override 245 | public YArrayList eachToEach(Collection other, BiFunction combinator) { 246 | return YCollections.eachToEach(this, other, combinator); 247 | } 248 | 249 | @Override 250 | public YArrayList eachToEach(List other, BiFunction combinator) { 251 | YArrayList result = new YArrayList<>(); 252 | for (int i = 0; i < this.size(); i++) { 253 | T a = this.get(i); 254 | for (int j = 0; j < other.size(); j++) { 255 | result.add(combinator.apply(a, other.get(j))); 256 | } 257 | } 258 | return result; 259 | } 260 | 261 | @Override 262 | public YArrayList mapUniquePares(BiFunction bf) { 263 | YArrayList result = al(); 264 | for (int i = 0; i < size()-1; i++) for (int j = i+1; j < size(); j++) result.add(bf.apply(get(i), get(j))); 265 | return result; 266 | } 267 | 268 | @Override 269 | public YArrayList> split(Predicate isSplitter) { 270 | YArrayList> result = al(); 271 | YArrayList cur = al(); 272 | for (T l : this) { 273 | if (isSplitter.test(l)) { 274 | result.add(cur); 275 | cur = al(); 276 | } else { 277 | cur.add(l); 278 | } 279 | } 280 | result.add(cur); 281 | return result; 282 | } 283 | 284 | //TODO test 285 | @Override 286 | public YArrayList reverse() { 287 | YArrayList result = al(); 288 | for (int i = this.size() - 1; i >= 0; i--) result.add(get(i)); 289 | return result; 290 | } 291 | 292 | /** 293 | * Removes last component and sets it in place of required. It allows to make remove without array copy. 294 | */ 295 | public T removeFast(int i) { 296 | if (i < 0 || i >= size()) throw new IndexOutOfBoundsException(i + " (list size: "+ size() + ")"); 297 | T old = get(i); 298 | if (i < size() - 1) set(i, remove(size() - 1)); else remove(i); 299 | return old; 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/test/java/yk/jcommon/collections/TestCollections.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Collection; 6 | 7 | import static junit.framework.Assert.assertEquals; 8 | import static org.junit.Assert.*; 9 | import static yk.jcommon.collections.YArrayList.al; 10 | import static yk.jcommon.collections.YHashMap.hm; 11 | import static yk.jcommon.collections.YHashSet.hs; 12 | 13 | public class TestCollections { 14 | 15 | public static void main1(String[] args) { 16 | YList all = al("shift", "ctrl", "alt", "super"); 17 | System.out.println(all.eachToEach(all) //take pares of each to each 18 | .map(p -> p //rework each pare 19 | .toSet() // convert to set to remove "alt alt" and similar 20 | .sorted() // sort (yes, it is a LinkedHashSet inside) 21 | .toString(", ") // make a string 22 | ) 23 | .toSet() //convert to set to remove duplicates ("alt shift", "shift alt") 24 | .sorted() //sort 25 | .toString("\n")); //make a result string 26 | } 27 | 28 | @Test 29 | public void testGroupBy() { 30 | assertEquals(hm(), YArrayList.al().groupBy(s -> s.length())); 31 | assertEquals(hm(0, al("")), al("").groupBy(s -> s.length())); 32 | assertEquals(hm(2, al("aa", "bb"), 1, al("b")), al("aa", "bb", "b").groupBy(s -> s.length())); 33 | } 34 | 35 | @Test 36 | public void testEachToEach() { 37 | YList all = al("shift", "ctrl", "alt", "super"); 38 | assertEquals("[[alt, ctrl], [alt, shift], [alt, super], [alt], [ctrl, shift], [ctrl, super], [ctrl], [shift, super], [shift], [super]]" 39 | , all.eachToEach(all).map(p -> p.toSet().toList().sorted().toString()).toSet().toList().sorted().toString()); 40 | 41 | assertEquals(al(al("a", "c"), al("a", "d"), al("b", "c"), al("b", "d")), al("a", "b").eachToEach(al("c", "d"))); 42 | 43 | assertEquals(al("ac", "ad", "bc", "bd"), al("a", "b").eachToEach(al("c", "d"), (a, b) -> a + b)); 44 | assertEquals(al(), al("a", "b").eachToEach(al(), (a, b) -> a + b)); 45 | assertEquals(al(), al().eachToEach(al("c", "d"), (a, b) -> a + b)); 46 | assertEquals(al("ac", "ad", "bc", "bd"), al("a", "b").eachToEach((Collection)al("c", "d"), (a, b) -> a + b)); 47 | assertEquals(al("ac", "ad", "bc", "bd"), al("a", "b").eachToEach(al("c", "d"), (a, b) -> a + b)); 48 | } 49 | 50 | @Test 51 | public void testReduce() { 52 | //System.out.println(al(2, 3, 4).fold(1, (a, b) -> a * b)); ahaha - internal compilator error 53 | assertEquals(9, (int)al(2, 3, 4).reduce(0, (a, b) -> a + b)); 54 | assertEquals(24, (int)al(2, 3, 4).reduce(1, (a, b) -> a * b)); 55 | YArrayList l = al(); 56 | assertEquals(1, (int) l.reduce(1, (a, b) -> a * b)); 57 | } 58 | 59 | @Test 60 | public void testIfEmpty() { 61 | assertEquals("isEmpty", al().ifEmpty("isEmpty", (l) -> (String)l.first())); 62 | assertEquals("a", al("a", "b").ifEmpty("isEmpty", (l) -> l.first())); 63 | } 64 | 65 | private static void testSort(YCollection c) { 66 | assertEquals(al(1), c.with(1).sorted(v -> -v).toList()); 67 | assertEquals(al(4, 3, 2, 1), c.with(1, 2, 3, 4).sorted(v -> -v).toList()); 68 | assertEquals(al(), c.with().sorted(v -> -v).toList()); 69 | 70 | assertEquals(al(1), c.with(1).sorted((o1, o2) -> -o1.compareTo(o2)).toList()); 71 | assertEquals(al(4, 3, 2, 1), c.with(1, 2, 3, 4).sorted((o1, o2) -> -o1.compareTo(o2)).toList()); 72 | assertEquals(al(), c.with().sorted((o1, o2) -> -o1.compareTo(o2)).toList()); 73 | 74 | assertEquals(al(1), c.with(1).sorted().toList()); 75 | assertEquals(al(1, 2, 3, 4), c.with(4, 3, 2, 1).sorted().toList()); 76 | assertEquals(al(), c.with().sorted().toList()); 77 | } 78 | 79 | private static void testMax(YCollection c) { 80 | try { 81 | c.max(); 82 | fail(); 83 | } catch (Exception ignore) {} 84 | assertEquals((Integer) 4, c.with(1, 2, 3, 4).max()); 85 | assertEquals((Integer) 4, c.with(1, 2, 4, 3).max()); 86 | assertEquals((Integer) 4, c.with(4, 1, 2, 3).max()); 87 | assertEquals((Integer) 4, c.with(4).max()); 88 | 89 | try { 90 | c.max((o1, o2) -> o1.compareTo(o2)); 91 | fail(); 92 | } catch (Exception ignore) {} 93 | assertEquals((Integer) 1, c.with(1, 2, 3, 4).max((o1, o2) -> -o1.compareTo(o2))); 94 | assertEquals((Integer) 1, c.with(2, 1, 3, 4).max((o1, o2) -> -o1.compareTo(o2))); 95 | assertEquals((Integer) 1, c.with(2, 3, 4, 1).max((o1, o2) -> -o1.compareTo(o2))); 96 | assertEquals((Integer) 1, c.with(1).max((o1, o2) -> -o1.compareTo(o2))); 97 | 98 | try { 99 | c.max(i -> -i); 100 | fail(); 101 | } catch (Exception ignore) {} 102 | assertEquals((Integer) 1, c.with(1, 2, 3, 4).max(i -> -i)); 103 | assertEquals((Integer) 1, c.with(2, 1, 3, 4).max(i -> -i)); 104 | assertEquals((Integer) 1, c.with(2, 3, 4, 1).max(i -> -i)); 105 | assertEquals((Integer) 1, c.with(1, 3, 4, 2).max(i -> -i)); 106 | assertEquals((Integer) 1, c.with(1).max(i -> -i)); 107 | 108 | try { 109 | c.maxByFloat(i -> -i); 110 | fail(); 111 | } catch (Exception ignore) {} 112 | assertEquals((Integer) 1, c.with(1, 2, 3, 4).maxByFloat(i -> -i)); 113 | assertEquals((Integer) 1, c.with(2, 1, 3, 4).maxByFloat(i -> -i)); 114 | assertEquals((Integer) 1, c.with(2, 3, 4, 1).maxByFloat(i -> -i)); 115 | assertEquals((Integer) 1, c.with(1, 3, 4, 2).maxByFloat(i -> -i)); 116 | assertEquals((Integer) 1, c.with(1).maxByFloat(i -> -i)); 117 | 118 | } 119 | 120 | private static void testMin(YCollection c) { 121 | try { 122 | c.min(); 123 | fail(); 124 | } catch (Exception ignore) {} 125 | assertEquals((Integer) 1, c.with(1, 2, 3, 4).min()); 126 | assertEquals((Integer) 1, c.with(2, 1, 3, 4).min()); 127 | assertEquals((Integer) 1, c.with(2, 3, 4, 1).min()); 128 | assertEquals((Integer) 1, c.with(1).min()); 129 | 130 | try { 131 | c.min((o1, o2) -> o1.compareTo(o2)); 132 | fail(); 133 | } catch (Exception ignore) {} 134 | assertEquals((Integer) 4, c.with(1, 2, 3, 4).min((o1, o2) -> -o1.compareTo(o2))); 135 | assertEquals((Integer) 4, c.with(1, 2, 4, 3).min((o1, o2) -> -o1.compareTo(o2))); 136 | assertEquals((Integer) 4, c.with(4, 1, 2, 3).min((o1, o2) -> -o1.compareTo(o2))); 137 | assertEquals((Integer) 4, c.with(4).min((o1, o2) -> -o1.compareTo(o2))); 138 | 139 | try { 140 | c.min(i -> i); 141 | fail(); 142 | } catch (Exception ignore) {} 143 | assertEquals((Integer) 4, c.with(1, 2, 3, 4).min(i -> -i)); 144 | assertEquals((Integer) 4, c.with(1, 2, 4, 3).min(i -> -i)); 145 | assertEquals((Integer) 4, c.with(4, 1, 2, 3).min(i -> -i)); 146 | assertEquals((Integer) 4, c.with(4).min(i -> -i)); 147 | 148 | try { 149 | c.minByFloat(i -> i); 150 | fail(); 151 | } catch (Exception ignore) {} 152 | assertEquals((Integer) 4, c.with(1, 2, 3, 4).minByFloat(i -> -i)); 153 | assertEquals((Integer) 4, c.with(1, 2, 4, 3).minByFloat(i -> -i)); 154 | assertEquals((Integer) 4, c.with(4, 1, 2, 3).minByFloat(i -> -i)); 155 | assertEquals((Integer) 4, c.with(4).minByFloat(i -> -i)); 156 | } 157 | 158 | private static void testCommon(YCollection c) { 159 | assertEquals(c, c.filter(x -> true)); 160 | assertEquals(c, c.with("2").filter(x -> !x.equals("2"))); 161 | assertEquals(c.emptyInstance().with("1"), c.with("1").filter(x -> x.equals("1"))); 162 | 163 | assertEquals("a", c.with("a", "b").firstOr(null)); 164 | assertEquals("a", c.with("a", "b").first()); 165 | assertEquals("b", c.with("b").firstOr("c")); 166 | assertEquals("b", c.with("b").first()); 167 | assertEquals("c", c.with().firstOr("c")); 168 | assertEquals(null, c.with().firstOr(null)); 169 | assertEquals("d", c.with().firstOrCalc(() -> "d")); 170 | assertEquals("a", c.with("a").firstOrCalc(() -> "d")); 171 | try { 172 | c.with().first(); 173 | fail(); 174 | } catch (Exception ignore) {} 175 | 176 | assertTrue(c.with("a", "b").isAny(s -> s.equals("a"))); 177 | assertFalse(c.with("a", "b").isAny(s -> s.equals("c"))); 178 | assertFalse(c.isAny(s -> s.equals("c"))); 179 | 180 | assertTrue(c.with("a", "b").isAll(s -> s.length() == 1)); 181 | assertFalse(c.with("a", "b", "cc").isAll(s -> s.length() == 1)); 182 | assertTrue(c.isAll(s -> s.length() == 1)); 183 | 184 | } 185 | 186 | private static void testForZip(YCollection c) { 187 | { 188 | YList sideEffects = al(); 189 | YCollection aa = c.with("a1", "a2"); 190 | YCollection bb = c.with("b1", "b2"); 191 | assertSame(aa, aa.forZip(bb, (a, b) -> sideEffects.addAll(al(a, b)))); 192 | assertEquals(al("a1", "b1", "a2", "b2"), sideEffects); 193 | } 194 | { 195 | YList sideEffects = al(); 196 | YCollection aa = c.emptyInstance(); 197 | YCollection bb = c.emptyInstance(); 198 | assertSame(aa, aa.forZip(bb, (a, b) -> sideEffects.addAll(al(a, b)))); 199 | assertEquals(al(), sideEffects); 200 | } 201 | { 202 | YList sideEffects = al(); 203 | YCollection aa = c.with("a1"); 204 | YCollection bb = c.emptyInstance(); 205 | try { 206 | aa.forZip(bb, (a, b) -> sideEffects.addAll(al(a, b))); 207 | fail(); 208 | } catch (RuntimeException ignore){} 209 | } 210 | } 211 | 212 | @Test 213 | public void testList() { 214 | testSort(al()); 215 | testMax(al()); 216 | testMin(al()); 217 | testCommon(al()); 218 | testForZip(al()); 219 | 220 | assertEquals("b", al("a", "b").lastOr("c")); 221 | assertEquals("b", al("a", "b").last()); 222 | assertEquals("b", al("b").lastOr("c")); 223 | assertEquals("b", al("b").last()); 224 | assertEquals("c", al().lastOr("c")); 225 | assertEquals(null, al().lastOr(null)); 226 | 227 | assertEquals("b", al("a", "b").lastOrCalc(() -> "c")); 228 | assertEquals("c", al().lastOrCalc(() -> "c")); 229 | try { 230 | al().last(); 231 | fail(); 232 | } catch (Exception ignore) {} 233 | } 234 | 235 | @Test 236 | public void testSet() { 237 | testSort(hs()); 238 | testMax(hs()); 239 | testMin(hs()); 240 | testCommon(hs()); 241 | testForZip(hs()); 242 | } 243 | 244 | } 245 | -------------------------------------------------------------------------------- /src/main/java/yk/jcommon/collections/YCollection.java: -------------------------------------------------------------------------------- 1 | package yk.jcommon.collections; 2 | 3 | import java.util.Collection; 4 | import java.util.Comparator; 5 | import java.util.Iterator; 6 | import java.util.function.*; 7 | 8 | import static yk.jcommon.collections.YArrayList.al; 9 | import static yk.jcommon.collections.YArrayList.toYList; 10 | import static yk.jcommon.collections.YHashMap.hm; 11 | import static yk.jcommon.collections.YHashSet.toYSet; 12 | 13 | //TODO tests and remove suppress UnusedDeclaration 14 | @SuppressWarnings("UnusedDeclaration") 15 | public interface YCollection extends Collection { 16 | 17 | YCollection emptyInstance(); 18 | 19 | YCollection filter(Predicate predicate); 20 | 21 | default YMap> groupBy(Function grouper) { 22 | YMap> result = hm(); 23 | for (T t : this) { 24 | K group = grouper.apply(t); 25 | YList gg = result.get(group); 26 | if (gg == null) { 27 | gg = al(); 28 | result.put(group, gg); 29 | } 30 | gg.add(t); 31 | } 32 | return result; 33 | } 34 | 35 | default boolean isAny(Predicate predicate) { 36 | for (T t : this) if (predicate.test(t)) return true; 37 | return false; 38 | } 39 | 40 | default boolean isAll(Predicate predicate) { 41 | for (T t : this) if (!predicate.test(t)) return false; 42 | return true; 43 | } 44 | 45 | YCollection map(Function mapper); 46 | 47 | //TODO test 48 | default YCollection mapWithIndex(BiFunction mapper) { 49 | Iterator it = iterator(); 50 | YCollection result = al(); 51 | for (int i = 0; i < size(); i++) { 52 | result.add(mapper.apply(i, it.next())); 53 | } 54 | return result; 55 | } 56 | 57 | //TODO test 58 | YCollection flatMap(Function> mapper); 59 | 60 | /** 61 | * The same as 'forEach', but returns 'this' so can continue using the instasnce. 62 | */ 63 | default YCollection forEachFun(Consumer consumer) { 64 | for (T t : this) consumer.accept(t); 65 | return this; 66 | } 67 | 68 | //TODO test 69 | default YCollection forZip(YCollection b, BiConsumer f) { 70 | Iterator i1 = this.iterator(); 71 | Iterator i2 = b.iterator(); 72 | while(true) { 73 | if (i1.hasNext() != i2.hasNext()) throw new RuntimeException("Expected the same size"); 74 | if (!i1.hasNext()) break; 75 | f.accept(i1.next(), i2.next()); 76 | } 77 | return this; 78 | } 79 | 80 | default YCollection forWithIndex(BiConsumer consumer) { 81 | Iterator it = iterator(); 82 | int i = 0; 83 | while(it.hasNext()) consumer.accept(i++, it.next()); 84 | return this; 85 | } 86 | 87 | default R reduce(R first, BiFunction folder) { 88 | R result = first; 89 | for (T t : this) result = folder.apply(result, t); 90 | return result; 91 | } 92 | 93 | //TODO test 94 | default T reduce(BiFunction folder) { 95 | if (isEmpty()) return null; 96 | Iterator i = iterator(); 97 | T result = i.next(); 98 | while (i.hasNext()) result = folder.apply(result, i.next()); 99 | return result; 100 | } 101 | 102 | //TODO test 103 | default T car() { 104 | return iterator().next(); 105 | } 106 | 107 | //TODO test 108 | default T cadr() { 109 | Iterator iterator = iterator(); 110 | iterator.next(); 111 | return iterator.next(); 112 | } 113 | 114 | YCollection cdr(); 115 | 116 | default T first() { 117 | return car(); 118 | } 119 | 120 | default T firstOr(T t) { 121 | if (isEmpty()) return t; 122 | return first(); 123 | } 124 | 125 | default T firstOrCalc(Supplier supplier) { 126 | if (isEmpty()) return supplier.get(); 127 | return first(); 128 | } 129 | 130 | //TODO test 131 | default T first(Predicate predicate) { 132 | for (T t : this) if (predicate.test(t)) return t; 133 | return null; 134 | } 135 | 136 | //TODO firstOr(Predicate predicate, T default) 137 | //TODO lastOr(Predicate predicate, T default) 138 | 139 | //TODO test 140 | default T last(Predicate predicate) { 141 | T result = null; 142 | for (T t : this) if (predicate.test(t)) result = t; 143 | return result; 144 | } 145 | 146 | default T max() { 147 | return YCollections.maxFromCollection(this); 148 | } 149 | 150 | default T max(Comparator comparator) { 151 | return YCollections.maxFromCollection(this, comparator); 152 | } 153 | 154 | default > T max(Function evaluator) { 155 | if (isEmpty()) throw new RuntimeException("can't get max on empty collection"); 156 | T max = null; 157 | CMP maxComparable = null; 158 | for (T t : this) { 159 | CMP nextComparable = evaluator.apply(t); 160 | if (nextComparable == null) throw new RuntimeException("evaluator shouldn't return null values"); 161 | if (maxComparable == null || maxComparable.compareTo(nextComparable) < 0) { 162 | max = t; 163 | maxComparable = nextComparable; 164 | } 165 | } 166 | return max; 167 | } 168 | 169 | default T maxByFloat(Function_float_T evaluator) { 170 | if (isEmpty()) throw new RuntimeException("can't get max on empty collection"); 171 | T max = null; 172 | float maxComparable = 0; 173 | boolean found = false; 174 | for (T t : this) { 175 | float nextComparable = evaluator.apply(t); 176 | if (!found || nextComparable > maxComparable) { 177 | max = t; 178 | maxComparable = nextComparable; 179 | } 180 | found = true; 181 | } 182 | return max; 183 | } 184 | 185 | default T min() { 186 | return YCollections.minFromCollection(this); 187 | } 188 | 189 | default T min(Comparator comparator) { 190 | return YCollections.minFromCollection(this, comparator); 191 | } 192 | 193 | default > T min(Function evaluator) { 194 | if (isEmpty()) throw new RuntimeException("can't get min on empty collection"); 195 | T min = null; 196 | CMP minComparable = null; 197 | for (T t : this) { 198 | CMP nextComparable = evaluator.apply(t); 199 | if (nextComparable == null) throw new RuntimeException("evaluator shouldn't return null values"); 200 | if (minComparable == null || minComparable.compareTo(nextComparable) >= 0) { 201 | min = t; 202 | minComparable = nextComparable; 203 | } 204 | } 205 | return min; 206 | } 207 | 208 | default T minByFloat(Function_float_T evaluator) { 209 | if (isEmpty()) throw new RuntimeException("can't get min on empty collection"); 210 | T min = null; 211 | float minComparable = 0; 212 | boolean found = false; 213 | for (T t : this) { 214 | float nextComparable = evaluator.apply(t); 215 | if (!found || nextComparable < minComparable) { 216 | min = t; 217 | minComparable = nextComparable; 218 | } 219 | found = true; 220 | } 221 | return min; 222 | } 223 | 224 | default YSet toSet() { 225 | return toYSet(this); 226 | } 227 | 228 | default YList toList() { 229 | return toYList(this); 230 | } 231 | 232 | YCollection withAll(Collection c); 233 | 234 | YCollection with(T t); 235 | 236 | @SuppressWarnings("unchecked") 237 | YCollection with(T... t); 238 | 239 | YCollection withoutAll(Collection c); 240 | 241 | YCollection without(T t); 242 | @SuppressWarnings("unchecked") 243 | YCollection without(T... t); 244 | 245 | //TODO reversed 246 | //YSet returns not YSet but YList, because sorting algorithm itself creates list //TODO fix this? 247 | default YList sorted() { 248 | return YCollections.sortedCollection(this); 249 | } 250 | 251 | default YList sorted(Comparator comparator) { 252 | return YCollections.sortedCollection(this, comparator); 253 | } 254 | 255 | default YList sorted(Function evaluator) { 256 | return YCollections.sortedCollection(this, (v1, v2) -> evaluator.apply(v1).compareTo(evaluator.apply(v2))); 257 | } 258 | 259 | YCollection take(int count); 260 | 261 | //TODO test 262 | default int count(Predicate predicate) { 263 | int result = 0; 264 | for (T t : this) if (predicate.test(t)) result++; 265 | return result; 266 | } 267 | 268 | //TODO test 269 | @SuppressWarnings("unchecked") 270 | default boolean containsAll(T... tt) { 271 | for (T t : tt) if (!contains(t)) return false; 272 | return true; 273 | } 274 | 275 | //TODO test 276 | @SuppressWarnings("unchecked") 277 | default boolean containsAny(Collection tt) { 278 | for (T t : tt) if (contains(t)) return true; 279 | return false; 280 | } 281 | 282 | //TODO test 283 | @SuppressWarnings("unchecked") 284 | default boolean containsAny(T... tt) { 285 | for (T t : tt) if (contains(t)) return true; 286 | return false; 287 | } 288 | 289 | //TODO test 290 | default String toString(String infix) { 291 | StringBuilder sb = new StringBuilder(""); 292 | boolean was = false; 293 | for (Object o : this) { 294 | if (was) sb.append(infix); 295 | sb.append(o); 296 | was = true; 297 | } 298 | return sb.toString(); 299 | } 300 | 301 | //TODO test 302 | default String toStringSuffix(String suffix) { 303 | StringBuilder sb = new StringBuilder(""); 304 | for (Object o : this) sb.append(o).append(suffix); 305 | return sb.toString(); 306 | 307 | } 308 | 309 | //TODO test 310 | default String toStringInfix(String infix) { 311 | return toString(infix); 312 | } 313 | 314 | //TODO test 315 | default String toStringPrefixInfix(String prefix, String infix) { 316 | boolean first = true; 317 | StringBuilder sb = new StringBuilder(); 318 | for (Object o : this) { 319 | if (first) first = false; 320 | else sb.append(infix); 321 | sb.append(prefix).append(o == null ? "null" : o.toString()); 322 | } 323 | return sb.toString(); 324 | } 325 | 326 | //TODO test 327 | default String toStringPrefixSuffix(String prefix, String suffix) { 328 | StringBuilder sb = new StringBuilder(); 329 | for (Object o : this) { 330 | sb.append(prefix).append(o == null ? "null" : o.toString()).append(suffix); 331 | } 332 | return sb.toString(); 333 | } 334 | 335 | //TODO test 336 | default YMap toMapKeys(Function f) { 337 | YMap result = hm(); 338 | for (T k : this) result.put(k, f.apply(k)); 339 | return result; 340 | } 341 | 342 | //TODO test 343 | default boolean notEmpty() { 344 | return !isEmpty(); 345 | } 346 | 347 | default V ifEmpty(V v, Function, V> Else) { 348 | if (isEmpty()) return v; 349 | return Else.apply(this); 350 | } 351 | 352 | default YCollection assertSize(int s) { 353 | if (size() != s) throw new RuntimeException("Expected size " + s + " but was " + size()); 354 | return this; 355 | } 356 | } 357 | --------------------------------------------------------------------------------