Use persistent collections

This commit is contained in:
Clément Fournier 2019-08-29 00:33:54 +02:00
parent 9ff844921b
commit 8c82441265
5 changed files with 27 additions and 77 deletions

View File

@ -148,6 +148,11 @@
<artifactId>checker-qual</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.pcollections</groupId>
<artifactId>pcollections</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>

View File

@ -4,10 +4,11 @@
package net.sourceforge.pmd.lang.rule.internal;
import java.util.List;
import java.util.Set;
import java.util.function.BinaryOperator;
import org.pcollections.PSet;
/**
* Describes a particular {@linkplain #apply(Object, Object) binary operation}
* on a type {@code <U>}. That operation must satisfy the following requirements,
@ -38,11 +39,8 @@ interface Monoid<U> extends BinaryOperator<U> {
static <T> Monoid<Set<T>> forSet() {
return (Monoid<Set<T>>) MonoidImpl.SET_MONOID;
return (Monoid<Set<T>>) MonoidImpl.PSET_MONOID;
}
static <T> Monoid<List<T>> forList() {
return (Monoid<List<T>>) MonoidImpl.LIST_MONOID;
}
}

View File

@ -4,54 +4,30 @@
package net.sourceforge.pmd.lang.rule.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.pcollections.HashTreePSet;
import org.pcollections.PSet;
@SuppressWarnings("unchecked")
final class MonoidImpl {
// TODO using persistent collections would be beneficial.
static final Monoid<? extends List> LIST_MONOID = new Monoid<List>() {
@Override
public List apply(List l, List r) {
if (l.isEmpty()) {
return r;
} else if (r.isEmpty()) {
return l;
}
ArrayList more = new ArrayList(l.size() + r.size());
more.addAll(l);
more.addAll(r);
return more;
}
@Override
public List zero() {
return Collections.emptyList();
}
};
static final Monoid<? extends Set> SET_MONOID = new Monoid<Set>() {
static final Monoid PSET_MONOID = new Monoid<Set>() {
@Override
public Set apply(Set l, Set r) {
if (l.isEmpty()) {
return r;
} else if (r.isEmpty()) {
return l;
if (l instanceof PSet) {
return ((PSet) l).plusAll(r);
} else if (r instanceof PSet) {
return ((PSet) r).plusAll(l);
}
Set more = new LinkedHashSet(l);
more.addAll(r);
return more;
return HashTreePSet.from(l).plusAll(r);
}
@Override
public Set zero() {
return Collections.emptySet();
return HashTreePSet.empty();
}
};

View File

@ -4,15 +4,14 @@
package net.sourceforge.pmd.lang.rule.internal;
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
import static net.sourceforge.pmd.util.CollectionUtil.setOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
@ -24,18 +23,18 @@ public class LatticeRelationTest {
@Test
public void testLattice() {
LatticeRelation<Class<?>, List<String>> lattice = new LatticeRelation<>(Monoid.forList(), TopoOrder.TYPE_HIERARCHY_ORDERING);
LatticeRelation<Class<?>, Set<String>> lattice = new LatticeRelation<>(Monoid.forSet(), TopoOrder.TYPE_HIERARCHY_ORDERING);
lattice.put(String.class, Collections.singletonList("string"));
lattice.put(Integer.class, Collections.singletonList("int"));
lattice.put(Long.class, Collections.singletonList("long"));
lattice.put(String.class, setOf("string"));
lattice.put(Integer.class, setOf("int"));
lattice.put(Long.class, setOf("long"));
lattice.freeze();
assertEquals(listOf("string", "int", "long"), lattice.get(Object.class));
assertEquals(setOf("string", "int", "long"), lattice.get(Object.class));
Map<Class<?>, LatticeRelation<Class<?>, List<String>>.LNode> nodes = lattice.getNodes();
Map<Class<?>, LatticeRelation<Class<?>, Set<String>>.LNode> nodes = lattice.getNodes();
assertTrue(nodes.get(Object.class).hasDiamond);
assertFalse(nodes.get(Serializable.class).hasDiamond);

View File

@ -4,19 +4,11 @@
package net.sourceforge.pmd.lang.rule.internal;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
import static net.sourceforge.pmd.util.CollectionUtil.setOf;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
@ -43,26 +35,6 @@ public class MonoidTest {
}
@Test
public void testListMonoid() {
Monoid<List<String>> monoid = Monoid.forList();
this.neutralTest(monoid, Stream.of(
listOf(),
emptyList(),
listOf("a", "b"),
listOf("a")
));
assertEquals(listOf("c"), monoid.apply(new ArrayList<>(), singletonList("c")));
assertEquals(listOf("a", "c"), monoid.apply(listOf("a"), listOf("c")));
assertEquals(listOf("c", "a"), monoid.apply(listOf("c"), listOf("a")));
assertEquals(listOf("a", "c"), monoid.apply(listOf("a", "c"), emptyList()));
assertEquals(listOf("a", "c"), monoid.apply(listOf("a", "c"), listOf()));
}
private <T> void neutralTest(Monoid<T> monoid, Stream<T> generator) {
generator.forEach(t -> {
assertEquals(t, monoid.apply(t, monoid.zero()));