我正在使用Hibernate Search 3.6.2,我想在前面对特定文档进行排序。出于这个原因,我已经编写了一个自定义比较器-Inource,但不知何故它似乎不起作用。
我希望将包含这些首选值的文档排序到前面。
这是我到目前为止所做的:
public class PreferenceFieldComparatorSource<T> extends FieldComparatorSource {
private static final long serialVersionUID = -8959374194451783596L;
private final List<?> preferred;
private final Class<?> clazz;
private final StringBridge stringBridge;
@SafeVarargs
public PreferenceFieldComparatorSource(Class<T> clazz,
StringBridge stringBridge, T... preferred) {
this(clazz, stringBridge, Arrays.asList(preferred));
}
public PreferenceFieldComparatorSource(Class<T> clazz,
StringBridge stringBridge, List<T> preferred) {
this.clazz = clazz;
this.stringBridge = stringBridge;
this.preferred = preferred;
}
@Override
public FieldComparator<String> newComparator(final String fieldName,
int numHits, int sortPos, final boolean reversed)
throws IOException {
return new FieldComparator<String>() {
private String[] values;
private String bottom;
private String[] currentReaderValues;
@Override
public int compare(int slot1, int slot2) {
return this.compare(this.values[slot1], this.values[slot2]);
}
@Override
public int compareBottom(int doc) throws IOException {
return this.compare(this.bottom, this.currentReaderValues[doc]);
}
@Override
public void copy(int slot, int doc) throws IOException {
this.values[slot] = this.currentReaderValues[doc];
}
@Override
public void setBottom(int slot) {
this.bottom = this.values[slot];
}
@Override
public void setNextReader(IndexReader reader, int docBase)
throws IOException {
System.out.println("fieldName: " + fieldName);
this.currentReaderValues = new String[reader.maxDoc()];
this.values = new String[reader.maxDoc()];
for (int i = 0; i < currentReaderValues.length; ++i) {
try {
this.currentReaderValues[i] = reader.document(docBase)
.get(fieldName);
} catch (ClassCastException e) {
throw new IllegalArgumentException(
PreferenceFieldComparatorSource.this.stringBridge
+ " doesn't convert strings into "
+ PreferenceFieldComparatorSource.this.clazz);
}
}
}
@Override
public String value(int slot) {
return this.values[slot];
}
private int compare(Object first, Object second) {
// if none of the given values is in the preferred lists
// the index is -1 but the compare function will still work
// correctly
// and will only move the preferred ones.
int firstIndex = PreferenceFieldComparatorSource.this.preferred
.indexOf(PreferenceFieldComparatorSource.this.stringBridge
.objectToString(first));
int secondIndex = PreferenceFieldComparatorSource.this.preferred
.indexOf(PreferenceFieldComparatorSource.this.stringBridge
.objectToString(second));
int result = Integer.compare(firstIndex, secondIndex);
if (reversed) {
result *= -1;
}
return result;
}
};
}
}
似乎没有调用compare方法。对于这种情况,我在这堂课中做错了什么?
编辑:
澄清评论中的陈述:
@Override
protected boolean lessThan(final Entry hitA, final Entry hitB) {
assert hitA != hitB;
assert hitA.slot != hitB.slot;
int numComparators = comparators.length;
for (int i = 0; i < numComparators; ++i) {
final int c = reverseMul[i] * comparators[i].compare(hitA.slot,
hitB.slot);
if (c != 0) {
// Short circuit
return c > 0;
}
}
// avoid random sort order that could lead to duplicates (bug
#31241):
return hitA.doc > hitB.doc;
}
答案 0 :(得分:0)
我明白了。要么我误读了Sort类的文档,要么它错了。它清楚地表明它是连续排序的,但它并不像连续3次排序java列表那样。相反,它的行为更像是反向。
来自Hibernate-Search源代码:
@Override
protected boolean lessThan(final Entry hitA, final Entry hitB) {
assert hitA != hitB;
assert hitA.slot != hitB.slot;
int numComparators = comparators.length;
for (int i = 0; i < numComparators; ++i) {
final int c = reverseMul[i] * comparators[i].compare(hitA.slot,
hitB.slot);
if (c != 0) {
// Short circuit
return c > 0;
}
}
// avoid random sort order that could lead to duplicates (bug
#31241):
return hitA.doc > hitB.doc;
}
而且我的比较器错了:
public class PreferenceFieldComparatorSource<T> extends FieldComparatorSource {
private static final long serialVersionUID = -8959374194451783596L;
private final List<?> preferred;
private final Class<?> clazz;
private final TwoWayStringBridge stringBridge;
@SafeVarargs
public PreferenceFieldComparatorSource(Class<T> clazz,
TwoWayStringBridge stringBridge, T... preferred) {
this(clazz, stringBridge, Arrays.asList(preferred));
}
public PreferenceFieldComparatorSource(Class<T> clazz,
TwoWayStringBridge stringBridge, List<T> preferred) {
this.clazz = clazz;
this.stringBridge = stringBridge;
this.preferred = preferred;
}
@Override
public FieldComparator<String> newComparator(final String fieldName,
int numHits, int sortPos, final boolean reversed)
throws IOException {
return new FieldComparator<String>() {
private String[] values;
private String bottom;
private String[] currentReaderValues;
@Override
public int compare(int slot1, int slot2) {
return this.compare(this.values[slot1], this.values[slot2]);
}
@Override
public int compareBottom(int doc) throws IOException {
return this.compare(this.bottom, this.currentReaderValues[doc]);
}
@Override
public void copy(int slot, int doc) throws IOException {
this.values[slot] = this.currentReaderValues[doc];
}
@Override
public void setBottom(int slot) {
this.bottom = this.values[slot];
}
@Override
public void setNextReader(IndexReader reader, int docBase)
throws IOException {
this.currentReaderValues = new String[reader.maxDoc()];
this.values = new String[reader.maxDoc()];
for (int i = 0; i < currentReaderValues.length; ++i) {
try {
this.currentReaderValues[i] = reader.document(i)
.get(fieldName);
} catch (ClassCastException e) {
throw new IllegalArgumentException(
PreferenceFieldComparatorSource.this.stringBridge
+ " doesn't convert strings into "
+ PreferenceFieldComparatorSource.this.clazz);
}
}
}
@Override
public String value(int slot) {
return this.values[slot];
}
private int compare(Object first, Object second) {
int firstIndex = PreferenceFieldComparatorSource.this.preferred
.indexOf(PreferenceFieldComparatorSource.this.stringBridge
.stringToObject((String) first));
int secondIndex = PreferenceFieldComparatorSource.this.preferred
.indexOf(PreferenceFieldComparatorSource.this.stringBridge
.stringToObject((String) second));
int result;
if(firstIndex == -1 || secondIndex == -1) {
if(firstIndex == secondIndex) {
result = 0;
} else if(firstIndex == -1) {
result = 1;
} else {
result = -1;
}
} else {
result = Integer.compare(firstIndex, secondIndex);
}
if (reversed) {
result *= -1;
}
return result;
}
};
}
}