代码之家  ›  专栏  ›  技术社区  ›  I82Much

在处理基元类型时如何避免重复?

  •  13
  • I82Much  · 技术社区  · 16 年前

    我需要对各种基本类型执行算法;除了变量的类型不同,算法基本上是相同的。比如说,

    /**
    * Determine if <code>value</code> is the bitwise OR of elements of <code>validValues</code> array. 
    * For instance, our valid choices are 0001, 0010, and 1000.
    * We are given a value of 1001.  This is valid because it can be made from
    * ORing together 0001 and 1000.
    * On the other hand, if we are given a value of 1111, this is invalid because
    * you cannot turn on the second bit from left by ORing together those 3
    * valid values.
    */
    public static boolean isValid(long value, long[] validValues) {
        for (long validOption : validValues) {
            value &= ~validOption;
        }
        return value == 0;
    }
    
    public static boolean isValid(int value, int[] validValues) {
        for (int validOption : validValues) {
            value &= ~validOption;
        }
        return value == 0;
    }
    

    我怎样才能避免这种重复?我知道没有办法将基本数组泛化,所以我的手好像被绑住了。我有基本数组的实例,而不是say Number对象的装箱数组,所以我也不想走这条路。

    我知道有很多关于数组、自动装箱等原语的问题,但是我还没有看到它是以这种方式表达的,而且我还没有看到关于如何与这些数组交互的决定性答案。

    我想我可以这样做:

    public static<E extends Number> boolean isValid(E value, List<E> numbers) {
        long theValue = value.longValue();
        for (Number validOption : numbers) {
            theValue &= ~validOption.longValue();
        }
        return theValue == 0;
    }
    

    public static boolean isValid(long value, long[] validValues) {
        return isValid(value, Arrays.asList(ArrayUtils.toObject(validValues)));
    }
    
    public static boolean isValid(int value, int[] validValues) {
        return isValid(value, Arrays.asList(ArrayUtils.toObject(validValues)));
    }
    

    那真的好多了吗?这种方法将创建比原始实现多得多的对象,尽管它会使源代码干涸。对此事如有任何意见,将不胜感激。

    4 回复  |  直到 16 年前
        1
  •  7
  •   Community Mohan Dere    9 年前

    我以前也问过类似的问题( Managing highly repetitive code and documentation in Java java.util.Arrays 高度重复 在其算法中处理基元数组类型。

    实际上,源代码包含以下注释:

    七种基本类型的代码基本相同。这就是生活。

    我接受的答案建议使用一个代码生成器,它可以让您使用代码模板。还有一条评论说Sun/Oracle在内部也使用了模板系统。

    您也可以使用反射来减少重复,但这可能会很慢,而且可能不值得付出努力。如果要测试其性能,此代码段将演示以下技术:

    import java.lang.reflect.Array;
    
    static long maskFor(Class<?> c) {
        return (
            c.equals(int.class) ? 1L << Integer.SIZE :
            c.equals(short.class) ? 1L << Short.SIZE :
            c.equals(byte.class) ? 1L << Byte.SIZE :
            0
        ) - 1;
    }   
    public static void reflectPrimitiveNumericArray(Object arr) throws Exception {
        int length = Array.getLength(arr);
        Class<?> componentType = arr.getClass().getComponentType();
        long mask = maskFor(componentType);
        System.out.format("%s[%d] = { ", componentType, length);
        for (int i = 0; i < length; i++) {
            long el = Array.getLong(arr, i) & mask;
            System.out.print(Long.toBinaryString(el) + " ");
        }
        System.out.println("}");
    }
    

    你可以通过考试 int[] 对于 arr ,以及其他基元数组类型。一切都被扔进 long

    reflectPrimitiveNumericArray(new byte[] { (byte) 0xF0 });
    // byte[1] = { 11110000 }
    reflectPrimitiveNumericArray(new int[] { 0xF0F0F0F0 });
    // int[1] = { 11110000111100001111000011110000 }
    reflectPrimitiveNumericArray(new long[] { 0xF0F0F0F0F0F0F0F0L });
    // long[1] = { 1111000011110000111100001111000011110000111100001111000011110000 }
    
        2
  •  5
  •   Michael Myers KitsuneYMG    16 年前

    如果你往里面看 java.util.Arrays binarySearch , equals

    如果性能有问题,我不建议依赖自动装箱,但如果没有(在您分析完之后),它将是一个有效的选择。

        3
  •  2
  •   Tom    16 年前

        4
  •  1
  •   mgmiller    13 年前

    在以前的生活中,我们有一些原始类型的集合,它们针对金融数据进行了优化(内存中有数百万个订单,使用分块数组等等)。我们的解决方案很像Trove,有一些存根文件。“原始”源文件应该是。。。例如HashSet\u键。有一些存根类 钥匙 价值 ,我们遵循Trove的模型,使用ant任务生成HashSetInt、HashSetLong等。。。