001package conexp.fx.core.collections;
002
003import java.io.BufferedWriter;
004import java.io.File;
005import java.io.FileWriter;
006import java.io.IOException;
007
008/*
009 * #%L
010 * Concept Explorer FX
011 * %%
012 * Copyright (C) 2010 - 2019 Francesco Kriegel
013 * %%
014 * This program is free software: you can redistribute it and/or modify
015 * it under the terms of the GNU General Public License as
016 * published by the Free Software Foundation, either version 3 of the
017 * License, or (at your option) any later version.
018 * 
019 * This program is distributed in the hope that it will be useful,
020 * but WITHOUT ANY WARRANTY; without even the implied warranty of
021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
022 * GNU General Public License for more details.
023 * 
024 * You should have received a copy of the GNU General Public
025 * License along with this program.  If not, see
026 * <http://www.gnu.org/licenses/gpl-3.0.html>.
027 * #L%
028 */
029
030import java.util.AbstractCollection;
031import java.util.AbstractList;
032import java.util.AbstractSet;
033import java.util.ArrayList;
034import java.util.Arrays;
035import java.util.Collection;
036import java.util.Collections;
037import java.util.Comparator;
038import java.util.Iterator;
039import java.util.List;
040import java.util.NoSuchElementException;
041import java.util.Random;
042import java.util.Set;
043import java.util.concurrent.ConcurrentHashMap;
044import java.util.function.BiPredicate;
045import java.util.function.Supplier;
046import java.util.stream.Collectors;
047
048import com.google.common.base.Function;
049import com.google.common.base.Predicate;
050import com.google.common.base.Predicates;
051import com.google.common.collect.Collections2;
052import com.google.common.collect.Iterables;
053import com.google.common.collect.Iterators;
054import com.google.common.collect.Lists;
055
056import conexp.fx.core.math.GuavaIsomorphism;
057
058public final class Collections3 {
059
060  public static final <E> Set<Set<E>> quotient(final Set<E> set, BiPredicate<E, E> pred) {
061    return set
062        .parallelStream()
063        .map(x -> set.parallelStream().filter(y -> pred.test(x, y)).collect(Collectors.toSet()))
064        .collect(Collectors.toSet());
065  }
066
067  public static final <E> Set<E> representatives(final Set<E> set, BiPredicate<E, E> pred) {
068    return quotient(set, pred).parallelStream().map(eqclass -> eqclass.iterator().next()).collect(Collectors.toSet());
069  }
070
071  public static final <E> Set<E> newConcurrentHashSet() {
072    return Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());
073  }
074
075  public static final BitSetFX integers(final int n) {
076//    return Stream.iterate(0, k -> k + 1).limit(n).collect(Collectors.toSet());
077    final BitSetFX s = new BitSetFX();
078    s.addRange(0, n);
079    return s;
080  }
081
082  public static final <E extends Number & Comparable<E>> double sum(final Collection<? extends E> c) {
083    double s = 0d;
084    for (E e : c)
085      s += e.doubleValue();
086    return s;
087  }
088
089  public static final <E extends Number & Comparable<E>> double avg(final Collection<? extends E> c) {
090    return sum(c) / (double) c.size();
091  }
092
093  public static final <E> Collection<E> union(final Collection<Collection<E>> c) {
094    return new AbstractCollection<E>() {
095
096      public final Iterator<E> iterator() {
097        return Iterables.concat(c).iterator();
098      }
099
100      public final int size() {
101        int size = 0;
102        for (Collection<? extends E> _c : c)
103          size += _c.size();
104        return size;
105      }
106    };
107  }
108
109  @SafeVarargs
110  public static final <E> Collection<E> union(final Collection<E>... c) {
111    return union(Arrays.asList(c));
112  }
113
114  public static final <E> Collection<E> union(final Collection<? extends E> c1, final Collection<? extends E> c2) {
115    return new AbstractCollection<E>() {
116
117      public final Iterator<E> iterator() {
118        return Iterators.concat(c1.iterator(), c2.iterator());
119      }
120
121      public final int size() {
122        return c1.size() + c2.size();
123      }
124    };
125  }
126
127  public static final <E> Collection<E> intersection(final Collection<E> c1, final Collection<? extends E> c2) {
128    return Collections2.filter(c1, Predicates.in(c2));
129  }
130
131  public static final <E> Collection<E> difference(final Collection<E> c1, final Collection<? extends E> c2) {
132    return Collections2.<E> filter(c1, Predicates.not(Predicates.in(c2)));
133  }
134
135  public static final <T, E> Set<E> transform(final Set<T> s, final GuavaIsomorphism<T, E> f) {
136    return new AbstractSet<E>() {
137
138      @Override
139      public final Iterator<E> iterator() {
140        return Iterators.transform(s.iterator(), f);
141      }
142
143      @Override
144      public final int size() {
145        return s.size();
146      }
147    };
148  }
149
150  public static final <E> E random(final Collection<? extends E> c, final Random rng) {
151    if (c.isEmpty())
152      throw new NoSuchElementException();
153    final int i = rng.nextInt(c.size());
154    if (c instanceof List) {
155      final List<? extends E> l = (List<? extends E>) c;
156      return l.get(i);
157    }
158    int j = 0;
159    for (E e : c)
160      if (j++ == i)
161        return e;
162    throw new NoSuchElementException();
163  }
164
165  public static final <E> E random(final Collection<? extends E> c, final Predicate<E> p, final Random rng) {
166    E e;
167    while (true) {
168      e = random(c, rng);
169      if (p.apply(e))
170        break;
171    }
172    return e;
173  }
174
175  public static final <E extends Comparable<E>> List<E> sort(final Iterable<? extends E> i) {
176    final ArrayList<E> l = Lists.newArrayList(i);
177    Collections.sort(l);
178    return l;
179  }
180
181  public static final <E> List<E> sort(final Iterable<? extends E> i, final Comparator<? super E> c) {
182    final ArrayList<E> l = Lists.newArrayList(i);
183    Collections.sort(l, c);
184    return l;
185  }
186
187  public static final <E, T extends E> Collection<T> elementsBySubClass(final Collection<E> c, final Class<T> clazz) {
188    return Collections2.transform(Collections2.filter(c, Predicates.instanceOf(clazz)), new Function<E, T>() {
189
190      public final T apply(final E e) {
191        return clazz.cast(e);
192      }
193    });
194  }
195
196  public static final <E> Function<Set<E>, Iterator<E>> setToIterator() {
197    return new Function<Set<E>, Iterator<E>>() {
198
199      public final Iterator<E> apply(final Set<E> it) {
200        return it.iterator();
201      }
202    };
203  }
204
205  public static final <E> Set<E> fromIterator(final Supplier<Iterator<E>> its) {
206    return new AbstractSet<E>() {
207
208      @Override
209      public Iterator<E> iterator() {
210        return its.get();
211      }
212
213      @Override
214      public int size() {
215        return Iterators.size(iterator());
216      }
217    };
218  }
219
220  public static final <E> Iterable<E> iterable(final Iterator<E> it) {
221    return new Iterable<E>() {
222
223      @Override
224      public Iterator<E> iterator() {
225        return it;
226      }
227    };
228  }
229
230  public static final Predicate<Integer> isSmaller(final int n) {
231    return new Predicate<Integer>() {
232
233      public final boolean apply(final Integer m) {
234        return m < n;
235      }
236    };
237  }
238
239  public static final <E> E firstElement(final Iterable<E> it) {
240    return it.iterator().next();
241  }
242
243  public static final <E> Function<Iterable<E>, E> firstElement() {
244    return new Function<Iterable<E>, E>() {
245
246      public final E apply(final Iterable<E> it) {
247        return it.iterator().next();
248      }
249    };
250  }
251
252//  public static final BitSetSetFX newBitSetSet(final Collection<Integer> c) {
253//    final BitSetSetFX b = new BitSetSetFX();
254//    b.addAll(c);
255//    return b;
256//  }
257
258//  public static final BitSetSet2 newBitSetSet2(final Collection<Integer> c) {
259//    final BitSetSet2 b = new BitSetSet2();
260//    b.addAll(c);
261//    return b;
262//  }
263
264  public static final <E> List<E> filter(final List<E> l, final Predicate<E> p) {
265    return new AbstractList<E>() {
266
267      public final E get(final int index) {
268        return Iterables.get(Iterables.filter(l, p), index);
269      }
270
271      public final int size() {
272        return Iterables.size(Iterables.filter(l, p));
273      }
274    };
275  }
276
277  public static final <T> void
278      writeToFile(final File file, final Collection<T> collection, final String prefix, final String... suffix)
279          throws IOException {
280    final BufferedWriter writer = new BufferedWriter(new FileWriter(file));
281    writer.append(prefix);
282    writer.append("size: " + collection.size());
283    // collection.stream().map(T::toString).forEach(bw::append);
284    for (T element : collection)
285      writer.append(element.toString());
286    if (suffix.length > 0)
287      writer.append(suffix[0]);
288    writer.close();
289  }
290}