代码之家  ›  专栏  ›  技术社区  ›  Aaron Roller

将番石榴范围转换为不同类型

  •  3
  • Aaron Roller  · 技术社区  · 10 年前

    如何转换给定的 Guava Range 从一种类型到另一种类型的范围。

    我希望有一个类似于Predicates.com pose的合成方法。以Integer和Long为例:

    Range<Integer> intRange = Range.compose(Range.atLeast(10l),integerFromLongFunction);
    

    我编写了compose方法:

        public static <F extends Comparable<F>, T extends Comparable<T>> Range<T> compose(Range<F> range,
            Function<F, T> function) {
        Range<T> result;
        if (range.hasUpperBound() && range.hasLowerBound()) {
            T upperEndpoint = function.apply(range.upperEndpoint());
            T lowerEndpoint = function.apply(range.lowerEndpoint());
            result = Range.range(lowerEndpoint, range.lowerBoundType(), upperEndpoint, range.upperBoundType());
        } else if (range.hasUpperBound()) {
            result = Range.upTo(function.apply(range.upperEndpoint()), range.upperBoundType());
        } else if (range.hasLowerBound()) {
            result = Range.downTo(function.apply(range.lowerEndpoint()), range.lowerBoundType());
        } else {
            result = Range.all();
        }
        return result;
    }
    

    单元测试:

    @Test
    public void testLongRangeToInteger() {
        Integer inRange = 6;
        Integer outOfRange = 3;
        Range<Long> longRange = Range.atLeast(5l);
        assertTrue(longRange.apply(inRange.longValue()));
        assertFalse(longRange.apply(outOfRange.longValue()));
    
        Function<Long, Integer> function = integerFromLongFunction();
        Range<Integer> intRange = RangeExtended.compose(longRange, function);
        assertTrue(intRange.apply(inRange));
        assertFalse(intRange.apply(outOfRange));
    }
    
    public static Function<Long, Integer> integerFromLongFunction() {
        return new Function<Long, Integer>() {
    
            @Override
            public Integer apply(Long input) {
                return (input == null) ? null : input.intValue();
            }
        };
    }
    

    我目前的愿望实际上是将Joda Duration转换为相应的毫秒,但为了简单起见,我用Long/Integer编写了示例。

    看起来瓜瓦会有这个,但我找不到任何地方。我使用的是v14,但查看最新的v17 javadoc并没有发现任何问题。

    2 回复  |  直到 10 年前
        1
  •  0
  •   Andy Thomas    3 年前

    在番石榴31.1中,似乎仍然不是一种方便的转换方法。

    一个简单的实现是:

    public static <T extends Comparable<T>, U extends Comparable<U>>
    @Nonnull Range<U> toRangeType( 
        @Nonnull Range<T> t, 
        @Nonnull Function<T,U> map ) 
    {
        Range<U> u;
        
        boolean hasLowerBound = t.hasLowerBound();
        boolean hasUpperBound = t.hasUpperBound();
        
        if ( hasLowerBound) {
            if ( hasUpperBound ) {
                u = Range.range(  
                        map.apply( t.lowerEndpoint()), t.lowerBoundType(), 
                        map.apply( t.upperEndpoint()), t.upperBoundType());
            }
            else {
                u = Range.downTo( map.apply( t.lowerEndpoint()), t.lowerBoundType());
            }
        }
        else {
            if ( hasUpperBound ) {
                u = Range.upTo( map.apply( t.upperEndpoint()), t.upperBoundType());
            }
            else {
                u = Range.all();
            }
        }
        
        return u;
    }
    
        2
  •  -1
  •   Jeff    3 年前
    
    package com.stackoverflow.q24889243;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    import java.time.Duration;
    import java.util.List;
    import java.util.function.Function;
    
    import com.google.common.collect.BoundType;
    import com.google.common.collect.Range;
    import org.joda.time.ReadableDuration;
    import org.junit.jupiter.api.Test;
    
    public class Answer {
    
        /**
         * Transforms one range to another
         *
         * @param <T>         the from type
         * @param <R>         the to type
         * @param fromRange   the from range
         * @param transformer the transformer
         *
         * @return the range
         */
        public static final <T extends Comparable<T>, R extends Comparable<R>> Range<R> transform(Range<T> fromRange,
                Function<? super T, ? extends R> transformer) {
    
            var hasLowerBound = fromRange.hasLowerBound();
            var hasUpperBound = fromRange.hasUpperBound();
    
            if (hasLowerBound && hasUpperBound) {
    
                var fromLowerEndpoint = fromRange.lowerEndpoint();
                var toLowerEndpoint = transformer.apply(fromLowerEndpoint);
    
                var fromUpperEndpoint = fromRange.upperEndpoint();
                var toUpperEndpoint = transformer.apply(fromUpperEndpoint);
    
                return Range.range(toLowerEndpoint, fromRange.lowerBoundType(), toUpperEndpoint,
                    fromRange.upperBoundType());
            }
    
            if (hasLowerBound) {
    
                var fromLowerEndpoint = fromRange.lowerEndpoint();
                var toLowerEndpoint = transformer.apply(fromLowerEndpoint);
    
                return Range.downTo(toLowerEndpoint, fromRange.lowerBoundType());
            }
    
            if (hasUpperBound) {
    
                var fromUpperEndpoint = fromRange.upperEndpoint();
                var toUpperEndpoint = transformer.apply(fromUpperEndpoint);
    
                return Range.upTo(toUpperEndpoint, fromRange.upperBoundType());
            }
    
            return Range.all();
        }
    
    
        @Test
        void testDurations() {
            assertRangeTransformer(Duration::toMillis, Duration.ofMillis(10), Duration.ofMillis(15));
    
            assertRangeTransformer(ReadableDuration::getMillis, org.joda.time.Duration.millis(10),
                org.joda.time.Duration.millis(15));
        }
    
        <T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformer(
                Function<? super T, ? extends R> transformer, T fromLowerBound, T fromUpperBound) {
    
            assertRangeTransformer(transformer, fromLowerBound, BoundType.CLOSED, fromUpperBound, BoundType.CLOSED);
            assertRangeTransformer(transformer, fromLowerBound, BoundType.CLOSED, fromUpperBound, BoundType.OPEN);
            assertRangeTransformer(transformer, fromLowerBound, BoundType.OPEN, fromUpperBound, BoundType.CLOSED);
            assertRangeTransformer(transformer, fromLowerBound, BoundType.OPEN, fromUpperBound, BoundType.OPEN);
    
            assertRangeTransformerLowerBoundOnly(transformer, fromLowerBound, BoundType.CLOSED);
            assertRangeTransformerLowerBoundOnly(transformer, fromLowerBound, BoundType.OPEN);
    
            assertRangeTransformerUpperBoundOnly(transformer, fromUpperBound, BoundType.CLOSED);
            assertRangeTransformerUpperBoundOnly(transformer, fromUpperBound, BoundType.OPEN);
    
            this.<T, R>assertRangeTransformerAll(transformer);
        }
    
        <T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformer(
                Function<? super T, ? extends R> transformer, T fromLowerBound, BoundType lowerBoundType, T fromUpperBound,
                BoundType upperBoundType) {
    
            var toLowerBound = transformer.apply(fromLowerBound);
            var toUpperBound = transformer.apply(fromUpperBound);
    
            var fromRange = Range.range(fromLowerBound, lowerBoundType, fromUpperBound, upperBoundType);
            var actualToRange = transform(fromRange, transformer);
            assertEquals(toLowerBound, actualToRange.lowerEndpoint());
            assertEquals(fromRange.lowerBoundType(), actualToRange.lowerBoundType());
            assertEquals(toUpperBound, actualToRange.upperEndpoint());
            assertEquals(fromRange.upperBoundType(), actualToRange.upperBoundType());
        }
    
        <T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerLowerBoundOnly(
                Function<? super T, ? extends R> transformer, T fromLowerBound, BoundType lowerBoundType) {
    
            var toLowerBound = transformer.apply(fromLowerBound);
            var fromRange = Range.downTo(fromLowerBound, lowerBoundType);
    
            var actualToRange = transform(fromRange, transformer);
            assertFalse(actualToRange.hasUpperBound());
            assertEquals(toLowerBound, actualToRange.lowerEndpoint());
            assertEquals(fromRange.lowerBoundType(), actualToRange.lowerBoundType());
        }
    
        <T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerUpperBoundOnly(
                Function<? super T, ? extends R> transformer, T fromUpperBound, BoundType upperBoundType) {
    
            var toLowerBound = transformer.apply(fromUpperBound);
            var fromRange = Range.upTo(fromUpperBound, upperBoundType);
    
            var actualToRange = transform(fromRange, transformer);
            assertFalse(actualToRange.hasLowerBound());
            assertEquals(toLowerBound, actualToRange.upperEndpoint());
            assertEquals(fromRange.upperBoundType(), actualToRange.upperBoundType());
    
        }
    
        <T extends Comparable<T>, R extends Comparable<R>> void assertRangeTransformerAll(
                Function<? super T, ? extends R> transformer) {
    
            var fromRange = Range.<T>all();
    
            var actualToRange = transform(fromRange, transformer);
            assertFalse(actualToRange.hasLowerBound());
            assertFalse(actualToRange.hasUpperBound());
    
        }
    }