Почему следующая фактически неиспользуемая строка (в методе: getAllDefinedVars ) влияет на конечный результат: List collect = allVars.stream (). Filter (v -> false) .collect (Collectors.toList ());
Если я удалю весь метод и одну строку кода , вызывающий этот метод (первая строка в generateOneSetOfBools ), в итоге я получаю другой результат. Я ожидал бы такого поведения, если бы ...
- указанная строка повлияла на список allVars или любую другую переменную
- результат потока будет использоваться
Насколько я понимаю, ничего из этого не происходит. Поэтому удаление всего этого метода не должно повлиять на результат.
Чтобы убедиться, вы можете запустить основную программу в первый раз с методом, содержащим поток, и второй раз без этого метода, а затем сравнить результат .
public class PairwiseMain {
private static PairwisePermutator pp = new PairwisePermutator();
public static void main(String[] args) {
for(int i = 0; i < 20; i++) {
pp.permutate(i);
System.out.println("----------------");
}
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class PairwisePermutator {
private int n;
public Stream<boolean[]> permutate(int n) {
this.n = n;
List<Var> vars = generateRequiredVars(n);
List<TupleSet> table = generateTable(vars);
generateCombinations(table, vars);
return null;
}
private void generateCombinations(List<TupleSet> table, List<Var> vars) {
TupleSet start = findStartTupleSet(table);
if(start == null) {
return;
}else {
Tuple t = start.tuples.get(0);
start.setVars(t);
generateOneSetOfBools(table, vars, new HashSet<>(Arrays.asList(start)));
}
System.out.println(Arrays.toString(vars.toArray()));
resetAllVars(vars);
generateCombinations(table, vars);
}
private void resetAllVars(List<Var> vars) {
vars.stream().forEach(v -> v.value = null);
}
private void generateOneSetOfBools(List<TupleSet> table, List<Var> allVars, Set<TupleSet> start) {
List<Var> alreadyDefinedVars = getAllDefinedVars(allVars); //REMOVAL OF THIS LINE SHOULD HAVE NO IMPACT
Map<TupleSet, Integer> relevant = findRelevantTuplesInOtherTupleSets(table, start);
boolean changes = false;
boolean existsMultipleOptions = false;
TupleSet minimalMultipleOptions = null;
int minimalMultipleOptionsNumber = Integer.MAX_VALUE;
for(Map.Entry<TupleSet, Integer> entry : relevant.entrySet()) {
if(entry.getValue() == -1) {
removeTuple(entry.getKey());
start.add(entry.getKey());
changes = true;
}else if(entry.getValue() == 1) {
changes = true;
removeTuple(entry.getKey(), table, allVars);
start.add(entry.getKey());
}else if(entry.getValue() >= 2) {
existsMultipleOptions = true;
if(entry.getValue() < minimalMultipleOptionsNumber) {
minimalMultipleOptionsNumber = entry.getValue();
minimalMultipleOptions = entry.getKey();
}
}
}
if(!changes && existsMultipleOptions) {
removeRandomTuple(minimalMultipleOptions, start);
}else if(!changes) {
setVars(table);
}
if(areAllVarsDefined(allVars)) {
removeMatchingTuples(table);
return;
}
generateOneSetOfBools(table, allVars, start);
}
private List<Var> getAllDefinedVars(List<Var> allVars) {
List<Var> collect = allVars.stream().filter(v -> false).collect(Collectors.toList());
return collect;
}
private void removeMatchingTuples(List<TupleSet> table) {
for(TupleSet ts : table) {
boolean v1 = ts.x.value;
boolean v2 = ts.y.value;
Tuple toRemove = null;
for(Tuple t : ts.tuples) {
if(t.a == v1 && t.b == v2) {
toRemove = t;
}
}
if(toRemove != null) {
ts.setVars(toRemove);
}
}
}
private boolean areAllVarsDefined(List<Var> allVars) {
return allVars.stream().filter(v -> v.value != null).count() == n;
}
private void removeRandomTuple(TupleSet minimalMultipleOptions, Set<TupleSet> start) {
Tuple toRemove = minimalMultipleOptions.tuples.get(0);
minimalMultipleOptions.setVars(toRemove);
start.add(minimalMultipleOptions);
}
private void setVars(List<TupleSet> table) {
boolean foundOne = false;
for(TupleSet ts : table) {
if(ts.x.value == null && ts.y.value == null) {
foundOne = setVars(ts);
}
}
if(!foundOne) {
for(TupleSet ts : table) {
if(ts.x.value == null || ts.y.value == null) {
if(ts.tuples.isEmpty()){
ts.x.value = true;
ts.y.value = false;
}else {
ts.setVars(ts.tuples.get(0));
}
}
}
}
}
private boolean setVars(TupleSet ts) {
boolean foundOne;
if(ts.tuples.isEmpty()){
ts.x.value = true;
ts.y.value = false;
foundOne = true;
}else {
ts.setVars(ts.tuples.get(0));
foundOne = true;
}
return foundOne;
}
private void removeTuple(TupleSet ts, List<TupleSet> table, List<Var> vars) {
Tuple toRemove = null;
if(ts.x.value != null) {
for(Tuple t : ts.tuples) {
if(t.a == ts.x.value) {
toRemove = t;
}
}
}else if(ts.y.value != null) {
for(Tuple t : ts.tuples) {
if(t.b == ts.y.value) {
toRemove = t;
}
}
}
if(toRemove != null)
ts.setVars(toRemove);
}
private void removeTuple(TupleSet ts) {
boolean v1 = ts.x.value;
boolean v2 = ts.y.value;
Tuple toRemove = null;
for(Tuple t : ts.tuples) {
if(t.a == v1 && t.b == v2) {
toRemove = t;
}
}
if(toRemove != null) {
ts.setVars(toRemove);
}
}
private Map<TupleSet, Integer> findRelevantTuplesInOtherTupleSets(List<TupleSet> table, Set<TupleSet> alreadyVisited) {
Map<TupleSet, Integer> freedomMap = new HashMap<>();
for(TupleSet ts : table) {
if(!alreadyVisited.contains(ts)) {
int degreeOfFreedom = calculateDegreeOfFreedom(ts);
freedomMap.put(ts, degreeOfFreedom); }
}
return freedomMap;
}
private int calculateDegreeOfFreedom(TupleSet ts) {
List<Var> alreadyDefinedVars = new ArrayList<>();
if(ts.x.value != null) {
alreadyDefinedVars.add(ts.x);
}
if(ts.y.value != null) {
alreadyDefinedVars.add(ts.y);
}
int degreeOfFreedom = 0;
if(areBothDefinied(alreadyDefinedVars)) {
degreeOfFreedom = -1;
}else if(isExactlyOneDefinied(alreadyDefinedVars)) {
Var defined = getDefinedVar(alreadyDefinedVars);
if(defined == ts.x) {
degreeOfFreedom = (int) ts.tuples.stream().filter(t -> t.a == ts.x.value).count();
}else if(defined == ts.y) {
degreeOfFreedom = (int) ts.tuples.stream().filter(t -> t.b == ts.y.value).count();
}
}else if(alreadyDefinedVars.isEmpty()) {
degreeOfFreedom = ts.tuples.size();
}
return degreeOfFreedom;
}
private Var getDefinedVar(List<Var> alreadyDefinedVars) {
return alreadyDefinedVars.get(0);
}
private boolean isExactlyOneDefinied(List<Var> alreadyDefinedVars) {
return alreadyDefinedVars.size() == 1;
}
private boolean areBothDefinied(List<Var> alreadyDefinedVars) {
return alreadyDefinedVars.size() == 2;
}
private TupleSet findStartTupleSet(List<TupleSet> table) {
TupleSet startingTupleSet = null;
for(TupleSet ts : table) {
if(!ts.tuples.isEmpty()) {
startingTupleSet = ts;
}
}
return startingTupleSet;
}
private List<Var> generateRequiredVars(int n) {
return IntStream.range(0, n).mapToObj(number -> new Var()).collect(Collectors.toList());
}
private List<TupleSet> generateTable(List<Var> vars) {
List<TupleSet> tupleSets = new ArrayList<>();
int kStart = 1;
for(int i = 0; i < vars.size(); i++) {
for(int k = kStart; k < vars.size(); k++) {
tupleSets.add(getInitSet(vars.get(i), vars.get(k)));
}
kStart++;
}
return tupleSets;
}
private TupleSet getInitSet(Var x, Var y){
return new TupleSet(x, y, (new ArrayList<>(Arrays.asList( new Tuple(true, true),
new Tuple(true, false),
new Tuple(false, true),
new Tuple(false, false)))));
}
private static class TupleSet{
Var x;
Var y;
ArrayList<Tuple> tuples;
TupleSet(Var x, Var y, ArrayList<Tuple> tuples){
this.x = x;
this.y = y;
this.tuples = tuples;
}
public void setVars(Tuple t) {
x.value = t.a;
y.value = t.b;
tuples.remove(t);
}
@Override
public String toString() {
return "["+x+","+y+"]"+tuples;
}
}
private static class Var{
public Boolean value;
@Override
public String toString() {
return value == null ? "null" : value.toString();
}
}
private static class Tuple{
public Boolean a;
public Boolean b;
public Tuple(Boolean a, Boolean b) {
this.a = a;
this.b = b;
}
@Override
public String toString() {
return "("+a+","+b+")";
}
}
}
Примером воздействия может быть запуск pp.permutate (5) со следующим выводом: С потоком: запустите код в том виде, в котором он был опубликован
[true, true, true, true, true]
[false, false, false, true, false]
[false, false, false, false, true]
[true, true, true, false, false]
[true, false, false, true, false]
[false, false, true, true, false]
[true, true, true, false, false]
Без потока: удалите только первую строку в generateOneSetOfBool ()
[true, true, true, true, true]
[false, false, false, true, false]
[false, false, false, false, true]
[true, true, true, false, false]
[false, true, true, true, false]
[true, false, true, true, false]
[true, true, false, false, false]
Оба выхода различаются, например, последний строка