001/* 002 * @author Francesco.Kriegel@gmx.de 003 */ 004package conexp.fx.core.collections.setlist; 005 006/*- 007 * #%L 008 * Concept Explorer FX 009 * %% 010 * Copyright (C) 2010 - 2019 Francesco Kriegel 011 * %% 012 * This program is free software: you can redistribute it and/or modify 013 * it under the terms of the GNU General Public License as 014 * published by the Free Software Foundation, either version 3 of the 015 * License, or (at your option) any later version. 016 * 017 * This program is distributed in the hope that it will be useful, 018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 020 * GNU General Public License for more details. 021 * 022 * You should have received a copy of the GNU General Public 023 * License along with this program. If not, see 024 * <http://www.gnu.org/licenses/gpl-3.0.html>. 025 * #L% 026 */ 027 028import java.util.Collection; 029import java.util.Comparator; 030import java.util.HashSet; 031import java.util.List; 032import java.util.Map; 033import java.util.Set; 034import java.util.Spliterator; 035import java.util.Spliterators; 036import java.util.concurrent.ConcurrentHashMap; 037import java.util.function.BiPredicate; 038 039import com.google.common.base.Predicate; 040import com.google.common.collect.Sets; 041 042import conexp.fx.core.collections.BitSetFX; 043import conexp.fx.core.math.GuavaIsomorphism; 044import conexp.fx.core.math.Isomorphism; 045 046public interface SetList<E> extends Set<E>, List<E>, Collection<E>, Iterable<E>, Cloneable { 047 048 public boolean set(Object o, E e); 049 050 public Collection<E> getAll(Collection<Integer> c, boolean includeNull); 051 052 public Collection<Integer> indicesOf(Collection<?> c, boolean includeMinusOne); 053 054 @Deprecated 055 public int lastIndexOf(Object o); 056 057 public SetList<E> filter(Predicate<? super E> p); 058 059 public SetList<E> subList(int from, int to); 060 061 public BitSetFX subBitSet(Collection<?> c); 062 063 public default HashSetArrayList<E> clone() { 064 return new HashSetArrayList<E>(this); 065 } 066 067 public default GuavaIsomorphism<E, Integer> indexGuava() { 068 return new GuavaIsomorphism<E, Integer>() { 069 070 @Override 071 public final Integer apply(final E e) { 072 return indexOf(e); 073 } 074 075 @Override 076 public final E invert(final Integer i) { 077 return get(i); 078 } 079 }; 080 } 081 082 public default Isomorphism<E, Integer> index() { 083 return new Isomorphism<E, Integer>(this::indexOf, this::get); 084 } 085 086 public default Isomorphism<E, Integer> currentIndex() { 087 final Map<E, Integer> indexOfMap = new ConcurrentHashMap<>(); 088 final Map<Integer, E> getMap = new ConcurrentHashMap<>(); 089 int i = 0; 090 for (E e : this) { 091 indexOfMap.put(e, i); 092 getMap.put(i, e); 093 i++; 094 } 095 return new Isomorphism<E, Integer>(indexOfMap::get, getMap::get); 096 } 097 098 @Override 099 default Spliterator<E> spliterator() { 100 return Spliterators.spliterator(this, Spliterator.ORDERED); 101 } 102 103 default LecticOrder<E> getLecticOrder() { 104 return new LecticOrder<E>(this); 105 } 106 107 public class LecticOrder<E> { 108 109 private final SetList<E> base; 110 111 private LecticOrder(final SetList<E> base) { 112 super(); 113 this.base = base; 114 } 115 116 public static final <T> Comparator<T> toComparator(final BiPredicate<T, T> isSmallerPredicate) { 117 return (x, y) -> x.equals(y) ? 0 : isSmallerPredicate.test(x, y) ? -1 : 1; 118 } 119 120 public final Comparator<E> getIndexComparator() { 121 return (x, y) -> { 122 final int i = base.indexOf(x); 123 final int j = base.indexOf(y); 124 if (i == j) 125 return 0; 126 if (i < j) 127 return -1; 128 return 1; 129 }; 130 } 131 132 public final Comparator<Set<E>> getLecticComparator() { 133 return toComparator(this::isSmaller); 134 } 135 136 public final Comparator<Set<E>> getLecticComparator(final E element) { 137 return toComparator((x, y) -> isSmaller(x, y, element)); 138 } 139 140 public final boolean isSmaller(final Set<E> set1, final Set<E> set2) { 141 return !set1.equals(set2) && Sets 142 .symmetricDifference(set1, set2) 143 .stream() 144 .sorted(getIndexComparator()) 145 .findFirst() 146 .map(set2::contains) 147 .get(); 148 } 149 150 public final boolean isSmaller(final Set<E> set1, final Set<E> set2, final E element) { 151// if (set1.equals(set2)) 152// return false; 153// if (!set2.contains(element)) 154// return false; 155// return Stream 156// .concat( 157// set1.parallelStream().filter( 158// s -> !set2.contains( 159// s)), 160// set2.parallelStream().filter( 161// s -> !set1.contains( 162// s))) 163// .min( 164// getSetListComparator( 165// base)) 166// .get() 167// .equals( 168// element); 169 return !set1.equals(set2) && set2.contains(element) && Sets 170 .symmetricDifference(set1, set2) 171 .stream() 172 .sorted(getIndexComparator()) 173 .findFirst() 174 .get() 175 .equals(element); 176 } 177 178 public final Set<E> oplus(final Set<E> set, final E m) { 179 final Set<E> result = new HashSet<E>(set); 180 result.retainAll(base.subList(0, base.indexOf(m))); 181 result.add(m); 182 return result; 183 } 184 185 } 186}