com.apple.foundationdb.tuple.IterableComparator Maven / Gradle / Ivy
/*
* IterableComparator.java
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.apple.foundationdb.tuple;
import java.util.Comparator;
import java.util.Iterator;
/**
* A {@link Tuple}-compatible {@link Comparator} that will sort {@link Iterable}s
* in a manner that is consistent with the byte-representation of {@link Tuple}s.
* In particular, if one has two {@link Tuple}s, {@code tuple1} and {@code tuple2},
* it is the case that:
*
*
* {@code
* tuple1.compareTo(tuple2)
* == new IterableComparator().compare(tuple1, tuple2)
* == new IterableComparator().compare(tuple1.getItems(), tuple2.getItems()),
* == ByteArrayUtil.compareUnsigned(tuple1.pack(), tuple2.pack())}
*
*
*
* The individual elements of the {@link Iterable} must be of a type that can
* be serialized by a {@link Tuple}. For items of identical types, they will be
* sorted in a way that is consistent with their natural ordering with a few
* caveats:
*
*
*
* -
* For floating point types, negative NaN values are sorted before all regular values, and
* positive NaN values are sorted after all regular values.
*
* -
* Single-precision floating point numbers are sorted before
* all double-precision floating point numbers.
*
* -
* UUIDs are sorted by their unsigned Big-Endian byte representation
* rather than their signed byte representation (which is the behavior of
* {@link java.util.UUID#compareTo(java.util.UUID) UUID.compareTo()}).
*
* - Strings are sorted explicitly by their UTF-8 byte representation
* - Nested {@link Tuple}s and {@link java.util.List List}s are sorted element-wise.
*
*/
public class IterableComparator implements Comparator> {
/**
* Creates a new {@code IterableComparator}. This {@link Comparator} has
* no internal state.
*/
public IterableComparator() {}
/**
* Compare two {@link Iterable}s in a way consistent with their
* byte representation. This is done element-wise and is consistent
* with a number of other ways of sorting {@link Tuple}s. This will
* raise an {@link IllegalArgumentException} if any of the items
* of either {@link Iterable} cannot be serialized by a {@link Tuple}.
*
* @param iterable1 the first {@link Iterable} of items
* @param iterable2 the second {@link Iterable} of items
* @return a negative number if the first iterable would sort before the second
* when serialized, a positive number if the opposite is true, and zero
* if the two are equal
*/
@Override
public int compare(Iterable> iterable1, Iterable> iterable2) {
Iterator> i1 = iterable1.iterator();
Iterator> i2 = iterable2.iterator();
while(i1.hasNext() && i2.hasNext()) {
int itemComp = TupleUtil.compareItems(i1.next(), i2.next());
if(itemComp != 0) {
return itemComp;
}
}
if(i1.hasNext()) {
// iterable2 is a prefix of iterable1.
return 1;
}
if(i2.hasNext()) {
// iterable1 is a prefix of iterable2.
return -1;
}
return 0;
}
}