【发布时间】:2021-10-30 06:56:56
【问题描述】:
我试图构造一个 MTree 类的对象 (https://github.com/Waikato/moa/blob/master/moa/src/main/java/moa/clusterers/outliers/utils/mtree/MTree.java)
MTree 的构造函数如下所示:
public MTree(DistanceFunction<? super DATA> distanceFunction,
SplitFunction<DATA> splitFunction) {
this(DEFAULT_MIN_NODE_CAPACITY, distanceFunction, splitFunction);
}
这里的DistanceFunction是一个接口,它的代码是:
/**
* An object that can calculate the distance between two data objects.
*
* @param <DATA> The type of the data objects.
*/
public interface DistanceFunction<DATA> {
double calculate(DATA data1, DATA data2);
}
它的实现是:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Some pre-defined implementations of {@linkplain DistanceFunction distance
* functions}.
*/
public final class DistanceFunctions {
/**
* Don't let anyone instantiate this class.
*/
private DistanceFunctions() {}
/**
* Creates a cached version of a {@linkplain DistanceFunction distance
* function}. This method is used internally by {@link MTree} to create
* a cached distance function to pass to the {@linkplain SplitFunction split
* function}.
* @param distanceFunction The distance function to create a cached version
* of.
* @return The cached distance function.
*/
public static <Data> DistanceFunction<Data> cached(final DistanceFunction<Data> distanceFunction) {
return new DistanceFunction<Data>() {
class Pair {
Data data1;
Data data2;
public Pair(Data data1, Data data2) {
this.data1 = data1;
this.data2 = data2;
}
@Override
public int hashCode() {
return data1.hashCode() ^ data2.hashCode();
}
@Override
public boolean equals(Object arg0) {
if(arg0 instanceof Pair) {
Pair that = (Pair) arg0;
return this.data1.equals(that.data1)
&& this.data2.equals(that.data2);
} else {
return false;
}
}
}
private final Map<Pair, Double> cache = new HashMap<Pair, Double>();
@Override
public double calculate(Data data1, Data data2) {
Pair pair1 = new Pair(data1, data2);
Double distance = cache.get(pair1);
if(distance != null) {
return distance;
}
Pair pair2 = new Pair(data2, data1);
distance = cache.get(pair2);
if(distance != null) {
return distance;
}
distance = distanceFunction.calculate(data1, data2);
cache.put(pair1, distance);
cache.put(pair2, distance);
return distance;
}
};
}
/**
* An interface to represent coordinates in Euclidean spaces.
* @see <a href="http://en.wikipedia.org/wiki/Euclidean_space">"Euclidean
* Space" article at Wikipedia</a>
*/
public interface EuclideanCoordinate {
/**
* The number of dimensions.
*/
int dimensions();
/**
* A method to access the {@code index}-th component of the coordinate.
*
* @param index The index of the component. Must be less than {@link
* #dimensions()}.
*/
double get(int index);
}
/**
* Calculates the distance between two {@linkplain EuclideanCoordinate
* euclidean coordinates}.
*/
public static double euclidean(EuclideanCoordinate coord1, EuclideanCoordinate coord2) {
int size = Math.min(coord1.dimensions(), coord2.dimensions());
double distance = 0;
for(int i = 0; i < size; i++) {
double diff = coord1.get(i) - coord2.get(i);
distance += diff * diff;
}
distance = Math.sqrt(distance);
return distance;
}
/**
* A {@linkplain DistanceFunction distance function} object that calculates
* the distance between two {@linkplain EuclideanCoordinate euclidean
* coordinates}.
*/
public static final DistanceFunction<EuclideanCoordinate> EUCLIDEAN = new DistanceFunction<DistanceFunctions.EuclideanCoordinate>() {
@Override
public double calculate(EuclideanCoordinate coord1, EuclideanCoordinate coord2) {
return DistanceFunctions.euclidean(coord1, coord2);
}
};
/**
* A {@linkplain DistanceFunction distance function} object that calculates
* the distance between two coordinates represented by {@linkplain
* java.util.List lists} of {@link java.lang.Integer}s.
*/
public static final DistanceFunction<List<Integer>> EUCLIDEAN_INTEGER_LIST = new DistanceFunction<List<Integer>>() {
@Override
public double calculate(List<Integer> data1, List<Integer> data2) {
class IntegerListEuclideanCoordinate implements EuclideanCoordinate {
List<Integer> list;
public IntegerListEuclideanCoordinate(List<Integer> list) { this.list = list; }
@Override public int dimensions() { return list.size(); }
@Override public double get(int index) { return list.get(index); }
};
IntegerListEuclideanCoordinate coord1 = new IntegerListEuclideanCoordinate(data1);
IntegerListEuclideanCoordinate coord2 = new IntegerListEuclideanCoordinate(data2);
return DistanceFunctions.euclidean(coord1, coord2);
}
};
/**
* A {@linkplain DistanceFunction distance function} object that calculates
* the distance between two coordinates represented by {@linkplain
* java.util.List lists} of {@link java.lang.Double}s.
*/
public static final DistanceFunction<List<Double>> EUCLIDEAN_DOUBLE_LIST = new DistanceFunction<List<Double>>() {
@Override
public double calculate(List<Double> data1, List<Double> data2) {
class DoubleListEuclideanCoordinate implements EuclideanCoordinate {
List<Double> list;
public DoubleListEuclideanCoordinate(List<Double> list) { this.list = list; }
@Override public int dimensions() { return list.size(); }
@Override public double get(int index) { return list.get(index); }
};
DoubleListEuclideanCoordinate coord1 = new DoubleListEuclideanCoordinate(data1);
DoubleListEuclideanCoordinate coord2 = new DoubleListEuclideanCoordinate(data2);
return DistanceFunctions.euclidean(coord1, coord2);
}
};
}
我的第一个问题是方法public static <Data> DistanceFunction<Data> cached(final DistanceFunction<Data> distanceFunction)中return new DistanceFunction<Data>()的含义是什么[方法在类DistanceFunctions中]我只是Java的初学者,这对我来说有点难以理解。
另外,要创建MTree的对象,我应该创建一个DistanceFunctions对象和一个ComposedSplitFunction对象(这是SplitFunction接口的实现)并将它们作为MTree构造函数的参数输入。但我真的不知道该怎么做,因为在 DistanceFunctions 类中,构造函数是私有的。所以我无法为 MTree 的构造函数生成参数。 我该怎么办?
新的更新:我想做的是为 MTree 创建一个 Junit 测试,我相信我需要做的第一件事就是创建一个 MTree 的对象。
【问题讨论】:
-
DistanceFunction是一个接口,你可以写一个类来实现它(其实一个lambda就可以了)。您还可以通过 EUCLEDIAN 等静态距离函数之一。很难就如何继续向您提供实际建议,因为您没有说出要对您尝试创建的 mtree 做什么。 -
我要做的是为MTree创建一个Junit Test,我相信我需要做的第一件事就是创建一个MTree的对象,这样我以后可以做更多的事情,对吧?跨度>