문제

나는 프로젝트에서 작업,작성된 자바에서 요구하는가 매우 큰 2-D 스파 배열입니다.매우 부족한 경우에는 차이가 있습니다.어쨌든:가장 중요한 측면에 대한 이 응용 프로그램은 효율성의 관점에서는 시간(가정의 로드 메모리하지 않지만,거의 그래서 무제한으로 허용하는 나에게 표준을 사용하는 2-D 배-키 범위에서 수십억에 두 차원).

의 kajillion 세포에서 배열이있을 것이다,여러 세포 포함하는 개체.필요를 수정할 수 있어야 합니다 셀의 내용을 매우 빠르게 합니다.

어쨌든:가 누구나 알고 특히 좋은 라이브러리 이러한 목적으?그것은 것을 버클리,LGPL 또는 이와 유사한 라이센스(no GPL,으로 제품을 수 없는 전적으로 오픈 소스).또는 있는 경우에만 매우 간단한 방법을 만들 브루 스파 배열체는 것무 문제가 없다는 것입니다.

MTJ, 하지만 듣지 못에 어떤 의견의 품질입니다.

도움이 되었습니까?

해결책

Sparsed 배열로 구축 해시맵은 매우 비효율적 자주를 위한 데이터를 읽.가장 효율적인 구현을 사용하여 라스에 대한 액세스를 허용하는 하나의 벡터는 세그먼트는 배포됩니다.

라을 계산할 수 있는 경우 요소가 존재에 테이블을 수행하여 읽기 전 두 배열 색인을 얻는 효과적인 위치는 요소는 저장하거나,알고 있는 경우에 없는 근본적인 저장합니다.

그것은 또한 제공할 수 있습니다 기본 위치에 백업 저장소에 대한 기본값의 sparsed 배열을,그래서 당신이 필요로 하지 않는 모든 테스트에서 반환된 색인이기 때문에,라 보장 가능한 모든 원본 지수는 지도에서 적어도 기본적인 입장에서 역행 저장(여기서 당신은 자주점 제로,또는 빈 문자열 또는 null object).

가 존재 구현을 지원하는 빠르게 업데이트할 수 있는 시도는 otional"compact()"작업을 optimze 크기의 역행 저장 끝에서의 여러 작업입니다.려고 하는 보다 훨씬 빠르게 해시맵기 때문에,그들은 그가 필요없는 복잡한 해쉬함수,그리고 필요가 없는 손잡이의 충돌에 대한 읽기(으로 해시맵,당신은 충돌을 모두 읽고,쓰기 위해 이 필요로 반복하는 다음의 후보자의 위치,그리고 테스트에서 그들 각각의 비교하는 효과적인 근원 index...)

또한,Java 해시맵 수 있는 인덱스에 객체를 만드는 정수에 대한 개체를 각자 해시된 원본의 인덱스(이 객체를 작성에 필요한 모든 읽기 뿐 아 씁니다)비용이 많이 드는 관점에서의 메모리 작업,그것을 강조한 쓰레기 수집기.

내가 정말 기대하는 이 JRE 를 포함되어 있는 IntegerTrieMap<Object> 기본적으로 구현하기 위한 HashMap<Integer, Object=""> 또 LongTrieMap<Object> 기본적으로 구현에 대해 더 HashMap<Long, Object="">...그러나 이것은 여전히지 않는 경우입니다.



가 무엇인지 궁금할 것 라?

그것은 단지 작은 정수 배열(에서 보다 작은 범위의 전체 범위에 대한 좌표의 행렬)할 수 있는 매핑 좌표는 정수에서의 위치를 벡터입니다.

예를 들어 원한다고 가정하 1024*1024 매트릭스만을 포함하는 몇 가지 비로 유지합니다.대신에 저장하는 매트릭스에 포함된 배열 1024*1024 요소(1 백만 개 이상),도 할 수 있으로 분할 하위 범위의 크기는 16*16,그리고 당신이해야 64*64 이러한 하위 범위.

이 경우,기술을 사용하여 색인이 포함 64*64 정수(4096),고 있을 것이 최소 16*16 데이터 요소(을 포함하는 기본 제로,또는 가장 일반적인 하위 범위에서 발견 sparse matrix).

과 벡터를 저장하는 데 사용되는 값만 포함됩 1 복사를 하위 범위는 각각 다른(의 대부분은 그들 전체의 제로,그들이 표현됩니다으로 동일한 하위 범위).

그래서 그 대신 사용하여 다음과 같은 구문을 matrix[i][j], 는,당신을 사용하여 다음과 같은 구문을:

trie.values[trie.subrangePositions[(i & ~15) + (j >> 4)] +
            ((i & 15) << 4) + (j & 15)]

는 것이 더 편리하게 사용하여 처리 접근 방식에 대한 라 개체입니다.

여기에 예를 들어,내장으로 주석 클래스(나는 그것을 컴파일하고 있으며 그것은 간체;신류가 있는 경우에는 정정하):

/**
 * Implement a sparse matrix. Currently limited to a static size
 * (<code>SIZE_I</code>, <code>SIZE_I</code>).
 */
public class DoubleTrie {

    /* Matrix logical options */        
    public static final int SIZE_I = 1024;
    public static final int SIZE_J = 1024;
    public static final double DEFAULT_VALUE = 0.0;

    /* Internal splitting options */
    private static final int SUBRANGEBITS_I = 4;
    private static final int SUBRANGEBITS_J = 4;

    /* Internal derived splitting constants */
    private static final int SUBRANGE_I =
        1 << SUBRANGEBITS_I;
    private static final int SUBRANGE_J =
        1 << SUBRANGEBITS_J;
    private static final int SUBRANGEMASK_I =
        SUBRANGE_I - 1;
    private static final int SUBRANGEMASK_J =
        SUBRANGE_J - 1;
    private static final int SUBRANGE_POSITIONS =
        SUBRANGE_I * SUBRANGE_J;

    /* Internal derived default values for constructors */
    private static final int SUBRANGES_I =
        (SIZE_I + SUBRANGE_I - 1) / SUBRANGE_I;
    private static final int SUBRANGES_J =
        (SIZE_J + SUBRANGE_J - 1) / SUBRANGE_J;
    private static final int SUBRANGES =
        SUBRANGES_I * SUBRANGES_J;
    private static final int DEFAULT_POSITIONS[] =
        new int[SUBRANGES](0);
    private static final double DEFAULT_VALUES[] =
        new double[SUBRANGE_POSITIONS](DEFAULT_VALUE);

    /* Internal fast computations of the splitting subrange and offset. */
    private static final int subrangeOf(
            final int i, final int j) {
        return (i >> SUBRANGEBITS_I) * SUBRANGE_J +
               (j >> SUBRANGEBITS_J);
    }
    private static final int positionOffsetOf(
            final int i, final int j) {
        return (i & SUBRANGEMASK_I) * MAX_J +
               (j & SUBRANGEMASK_J);
    }

    /**
     * Utility missing in java.lang.System for arrays of comparable
     * component types, including all native types like double here.
     */
    public static final int arraycompare(
            final double[] values1, final int position1,
            final double[] values2, final int position2,
            final int length) {
        if (position1 >= 0 && position2 >= 0 && length >= 0) {
            while (length-- > 0) {
                double value1, value2;
                if ((value1 = values1[position1 + length]) !=
                    (value2 = values2[position2 + length])) {
                    /* Note: NaN values are different from everything including
                     * all Nan values; they are are also neigher lower than nor
                     * greater than everything including NaN. Note that the two
                     * infinite values, as well as denormal values, are exactly
                     * ordered and comparable with <, <=, ==, >=, >=, !=. Note
                     * that in comments below, infinite is considered "defined".
                     */
                    if (value1 < value2)
                        return -1;        /* defined < defined. */
                    if (value1 > value2)
                        return 1;         /* defined > defined. */
                    if (value1 == value2)
                        return 0;         /* defined == defined. */
                    /* One or both are NaN. */
                    if (value1 == value1) /* Is not a NaN? */
                        return -1;        /* defined < NaN. */
                    if (value2 == value2) /* Is not a NaN? */
                        return 1;         /* NaN > defined. */
                    /* Otherwise, both are NaN: check their precise bits in
                     * range 0x7FF0000000000001L..0x7FFFFFFFFFFFFFFFL
                     * including the canonical 0x7FF8000000000000L, or in
                     * range 0xFFF0000000000001L..0xFFFFFFFFFFFFFFFFL.
                     * Needed for sort stability only (NaNs are otherwise
                     * unordered).
                     */
                    long raw1, raw2;
                    if ((raw1 = Double.doubleToRawLongBits(value1)) !=
                        (raw2 = Double.doubleToRawLongBits(value2)))
                        return raw1 < raw2 ? -1 : 1;
                    /* Otherwise the NaN are strictly equal, continue. */
                }
            }
            return 0;
        }
        throw new ArrayIndexOutOfBoundsException(
                "The positions and length can't be negative");
    }

    /**
     * Utility shortcut for comparing ranges in the same array.
     */
    public static final int arraycompare(
            final double[] values,
            final int position1, final int position2,
            final int length) {
        return arraycompare(values, position1, values, position2, length);
    }

    /**
     * Utility missing in java.lang.System for arrays of equalizable
     * component types, including all native types like double here.
     */ 
    public static final boolean arrayequals(
            final double[] values1, final int position1,
            final double[] values2, final int position2,
            final int length) {
        return arraycompare(values1, position1, values2, position2, length) ==
            0;
    }

    /**
     * Utility shortcut for identifying ranges in the same array.
     */
    public static final boolean arrayequals(
            final double[] values,
            final int position1, final int position2,
            final int length) {
        return arrayequals(values, position1, values, position2, length);
    }

    /**
     * Utility shortcut for copying ranges in the same array.
     */
    public static final void arraycopy(
            final double[] values,
            final int srcPosition, final int dstPosition,
            final int length) {
        arraycopy(values, srcPosition, values, dstPosition, length);
    }

    /**
     * Utility shortcut for resizing an array, preserving values at start.
     */
    public static final double[] arraysetlength(
            double[] values,
            final int newLength) {
        final int oldLength =
            values.length < newLength ? values.length : newLength;
        System.arraycopy(values, 0, values = new double[newLength], 0,
            oldLength);
        return values;
    }

    /* Internal instance members. */
    private double values[];
    private int subrangePositions[];
    private bool isSharedValues;
    private bool isSharedSubrangePositions;

    /* Internal method. */
    private final reset(
            final double[] values,
            final int[] subrangePositions) {
        this.isSharedValues =
            (this.values = values) == DEFAULT_VALUES;
        this.isSharedsubrangePositions =
            (this.subrangePositions = subrangePositions) ==
                DEFAULT_POSITIONS;
    }

    /**
     * Reset the matrix to fill it with the same initial value.
     *
     * @param initialValue  The value to set in all cell positions.
     */
    public reset(final double initialValue = DEFAULT_VALUE) {
        reset(
            (initialValue == DEFAULT_VALUE) ? DEFAULT_VALUES :
                new double[SUBRANGE_POSITIONS](initialValue),
            DEFAULT_POSITIONS);
    }

    /**
     * Default constructor, using single default value.
     *
     * @param initialValue  Alternate default value to initialize all
     *                      positions in the matrix.
     */
    public DoubleTrie(final double initialValue = DEFAULT_VALUE) {
        this.reset(initialValue);
    }

    /**
     * This is a useful preinitialized instance containing the
     * DEFAULT_VALUE in all cells.
     */
    public static DoubleTrie DEFAULT_INSTANCE = new DoubleTrie();

    /**
     * Copy constructor. Note that the source trie may be immutable
     * or not; but this constructor will create a new mutable trie
     * even if the new trie initially shares some storage with its
     * source when that source also uses shared storage.
     */
    public DoubleTrie(final DoubleTrie source) {
        this.values = (this.isSharedValues =
            source.isSharedValues) ?
            source.values :
            source.values.clone();
        this.subrangePositions = (this.isSharedSubrangePositions =
            source.isSharedSubrangePositions) ?
            source.subrangePositions :
            source.subrangePositions.clone());
    }

    /**
     * Fast indexed getter.
     *
     * @param i  Row of position to set in the matrix.
     * @param j  Column of position to set in the matrix.
     * @return   The value stored in matrix at that position.
     */
    public double getAt(final int i, final int j) {
        return values[subrangePositions[subrangeOf(i, j)] +
                      positionOffsetOf(i, j)];
    }

    /**
     * Fast indexed setter.
     *
     * @param i      Row of position to set in the sparsed matrix.
     * @param j      Column of position to set in the sparsed matrix.
     * @param value  The value to set at this position.
     * @return       The passed value.
     * Note: this does not compact the sparsed matric after setting.
     * @see compact(void)
     */
    public double setAt(final int i, final int i, final double value) {
       final int subrange       = subrangeOf(i, j);
       final int positionOffset = positionOffsetOf(i, j);
       // Fast check to see if the assignment will change something.
       int subrangePosition, valuePosition;
       if (Double.compare(
               values[valuePosition =
                   (subrangePosition = subrangePositions[subrange]) +
                   positionOffset],
               value) != 0) {
               /* So we'll need to perform an effective assignment in values.
                * Check if the current subrange to assign is shared of not.
                * Note that we also include the DEFAULT_VALUES which may be
                * shared by several other (not tested) trie instances,
                * including those instanciated by the copy contructor. */
               if (isSharedValues) {
                   values = values.clone();
                   isSharedValues = false;
               }
               /* Scan all other subranges to check if the position in values
                * to assign is shared by another subrange. */
               for (int otherSubrange = subrangePositions.length;
                       --otherSubrange >= 0; ) {
                   if (otherSubrange != subrange)
                       continue; /* Ignore the target subrange. */
                   /* Note: the following test of range is safe with future
                    * interleaving of common subranges (TODO in compact()),
                    * even though, for now, subranges are sharing positions
                    * only between their common start and end position, so we
                    * could as well only perform the simpler test <code>
                    * (otherSubrangePosition == subrangePosition)</code>,
                    * instead of testing the two bounds of the positions
                    * interval of the other subrange. */
                   int otherSubrangePosition;
                   if ((otherSubrangePosition =
                           subrangePositions[otherSubrange]) >=
                           valuePosition &&
                           otherSubrangePosition + SUBRANGE_POSITIONS <
                           valuePosition) {
                       /* The target position is shared by some other
                        * subrange, we need to make it unique by cloning the
                        * subrange to a larger values vector, copying all the
                        * current subrange values at end of the new vector,
                        * before assigning the new value. This will require
                        * changing the position of the current subrange, but
                        * before doing that, we first need to check if the
                        * subrangePositions array itself is also shared
                        * between instances (including the DEFAULT_POSITIONS
                        * that should be preserved, and possible arrays
                        * shared by an external factory contructor whose
                        * source trie was declared immutable in a derived
                        * class). */
                       if (isSharedSubrangePositions) {
                           subrangePositions = subrangePositions.clone();
                           isSharedSubrangePositions = false;
                       }
                       /* TODO: no attempt is made to allocate less than a
                        * fully independant subrange, using possible
                        * interleaving: this would require scanning all
                        * other existing values to find a match for the
                        * modified subrange of values; but this could
                        * potentially leave positions (in the current subrange
                        * of values) unreferenced by any subrange, after the
                        * change of position for the current subrange. This
                        * scanning could be prohibitively long for each
                        * assignement, and for now it's assumed that compact()
                        * will be used later, after those assignements. */
                       values = setlengh(
                           values,
                           (subrangePositions[subrange] =
                            subrangePositions = values.length) +
                           SUBRANGE_POSITIONS);
                       valuePosition = subrangePositions + positionOffset;
                       break;
                   }
               }
               /* Now perform the effective assignment of the value. */
               values[valuePosition] = value;
           }
       }
       return value;
    }

    /**
     * Compact the storage of common subranges.
     * TODO: This is a simple implementation without interleaving, which
     * would offer a better data compression. However, interleaving with its
     * O(N²) complexity where N is the total length of values, should
     * be attempted only after this basic compression whose complexity is
     * O(n²) with n being SUBRANGE_POSITIIONS times smaller than N.
     */
    public void compact() {
        final int oldValuesLength = values.length;
        int newValuesLength = 0;
        for (int oldPosition = 0;
                 oldPosition < oldValuesLength;
                 oldPosition += SUBRANGE_POSITIONS) {
            int oldPosition = positions[subrange];
            bool commonSubrange = false;
            /* Scan values for possible common subranges. */
            for (int newPosition = newValuesLength;
                    (newPosition -= SUBRANGE_POSITIONS) >= 0; )
                if (arrayequals(values, newPosition, oldPosition,
                        SUBRANGE_POSITIONS)) {
                    commonSubrange = true;
                    /* Update the subrangePositions|] with all matching
                     * positions from oldPosition to newPosition. There may
                     * be several index to change, if the trie has already
                     * been compacted() before, and later reassigned. */
                    for (subrange = subrangePositions.length;
                         --subrange >= 0; )
                        if (subrangePositions[subrange] == oldPosition)
                            subrangePositions[subrange] = newPosition;
                    break;
                }
            if (!commonSubrange) {
                /* Move down the non-common values, if some previous
                 * subranges have been compressed when they were common.
                 */
                if (!commonSubrange && oldPosition != newValuesLength) {
                    arraycopy(values, oldPosition, newValuesLength,
                        SUBRANGE_POSITIONS);
                    /* Advance compressed values to preserve these new ones. */
                    newValuesLength += SUBRANGE_POSITIONS;
                }
            }
        }
        /* Check the number of compressed values. */
        if (newValuesLength < oldValuesLength) {
            values = values.arraysetlength(newValuesLength);
            isSharedValues = false;
        }
    }

}

참고:이 코드가 완료되지 않을 처리하기 때문에 하나의 행렬은 크기와 분쇄기로 제한된 감지만 일반적인 하위 범위지 않고,인터리브니다.

또한,코드 확인하지 않는 곳에 그것은 최고의 너비나 높이를 사용한 나누는 매트릭스로 하위 범위(x,y)좌표에 따르면,행렬의 크기입니다.그것은 단지 사용하여 동일한 정적 하위 범위의 크기는 16 일(모두에 좌표)지만,그것은 될 수 있는 편리의 다른 작은 힘의 2(그러나 비원의 2 의 속도가 느려집 int indexOf(int, int)int offsetOf(int, int) 내부 방법),고 즐겁게 놀 수 있는 공간 모두에 대한 좌표와 최대 너비나 높이의 행렬입니다.스 compact() 해야하는 방법을 확인 할 수 있는 최고의 피팅 크기입니다.

는 경우 이러한 분할 하위 범위의 크기 다를 수 있습니다,그런 다음 필요가 있을 추가 인스턴스가 구성원을 위해 이러한 하위 범위의 크기는 대신 정적 SUBRANGE_POSITIONS, 을 정적 방법 int subrangeOf(int i, int j)int positionOffsetOf(int i, int j) 비 static;초기화는 배열 DEFAULT_POSITIONSDEFAULT_VALUES 야 합니다 떨어뜨리거나 재정의 다릅니다.

당신이 지원하려는 경우 인터리브,기본적으로 시작할 것을 나누어 기존에 있는 값의 두 가지에 대해 동일한 크기(모두되는 다수의 하위 범위에서 최소 크기,먼저 하위 집합을 가능하게 하나를 더 하위 범위에서 이상 두번째),그리고 당신은 스캔 큰 중 하나에 모든 연속적인 위치를 찾 인터리브;당신은 일치하려고 이러한 값입니다.당신은 루프 recursely 나누어 집합에 반(또한 다수의 하위 범위에서 최소 크기)그리고 당신이 검사를 다시 일치 하는 이러한 하위 집합(이 곱 수의 하위 집합이 2:이 있을 경우 배 크기의 subrangePositions 인덱스가 가치가 값에 비해 기존의 크기 값을 보면 그것이 제공하는 효과적인 압축(하지 않을 경우,당신은 거기서 멈추지:당신이 발견한 최적의 크기 하위 범위에서 직접 인터리브 압축 프로세스).는 경우;하위 범위의 크기 변경할 수는 동안 다짐.

하지만 이 코드에 할당하는 방법을 보여 줍니다 아닌 값을 재배치 data 배열에 대한 추가적인(non-zero)하위 범위,그리고 다음 방법을 최적화할 수 있습니다(과 compact() 후에 할당되었을 사용하여 수행됩 setAt(int i, int j, double value) 방법)이 데이터의 저장소가 있을 때 하위 범위 중복 될 수 있는 통합 데이터 내에서,그리고 다시 인덱싱에서 동일한 위치에서 subrangePositions 배열입니다.

어쨌든 모든 원리들의 뜨히 구현하기:

  1. 그것은 항상 빠르게(그리고 더 소형 메모리에 의미가 더 나은 지역)을 나타내는 매트릭스를 사용하여 하나의 벡터의 대신 두 번 색인 배열의 배열(각 할당된 별도).개선에서 보 double getAt(int, int) 방법!

  2. 당신이 많이 저장 공간을 할당할 때는 값은 그것은 시간이 걸릴 수 있습을 재배치하는 새로운 하위 범위.이러한 이유로,하위 범위가 너무 작거나 재할당 횟수이 너무 자주 발생을 설정하기 위한 당신의 행렬입니다.

  3. 그것은 가능한 변환 초기 큰 행렬로 자동적으로 더 콤팩트한 매트릭스를 감지하여 일반적인 하위 범위.일반적인 구현은 다음을 포함하는 등의 방법 compact() 니다.그러나면()에 액세스는 매우 빠르게 설정()은 매우 빠르고,compact()매우 느려질 수 있습니다 많은 경우의 일반적인 하위 범위를 압축하는(예를 들어 때 뺀 큰 비파스로 가득한 매트릭스 자체와,또는 곱하여 zero:그것은 간단하고 훨씬 더 빠르는 경우를 재설정 기술을 사용하여하여 instanciating 새로운 오래된 하나입니다).

  4. 일반적인 하위 범위 사용하여 일반적인 저장소에서 데이터,그래서 이 공유 데이터를 읽어야 합니다.변경해야 하는 경우에는 단일 값을 변경하지 않고 행렬의 나머지 부분에,당신은 먼저 해야 그것을 참조 하나만 시간 subrangePositions 인덱스이다.그렇지 않으면 당신을 할당해야 새로운 하위 범위에서 어디서나(편에 끝)의 values 벡터,그리고 다음의 위치를 저장하고 이 새로운 하위 범위로 subrangePositions 인덱스이다.



참고로 일반 라이브러리 콜트는,비록 매우 좋은것이 좋지 않을 때에 작업파스 목를 사용하기 때문에 해싱(또는 행 compresssed)기술하지 않는 구현에 대한 지원을 시도해 지금에도 불구하고,그것은 다양한 최적화를 모두 공간 절약 시간 절약,특히 위한 가장 자주 getAt()작업입니다.

도 setAt()작업하기 위해 여기에 설명되려고 많은 시간을 저장(는 방법은 구현되는 여기에서,즉자동 압축을 한 후 설정을 수있는,아직도 기반으로 구현 될 수요 예상 시간 곳은 압축 여전히 많이 저장한 저장 공간에서의 가격을 시간):시간을 절약에 비례한 세포의 많은 수의 하위 범위,공간 절약형 반비례하여 세포의 수당 하위 범위.좋은 compromize 는 경우 다음을 사용하여 하위 범위에서 이러한 크기의 수를 세포당 하위 범위는 사각형 뿌리의 총 수의 세포에서는 2D matrix(이 될 것 입방 루트로 작업할 때 3D 목).

해싱 기술에 사용되는 콜트 sparse matrix 구현 있는 그들은 많이 추가의 오버헤드 저장소,그리고 느리게 액세스 시간을 가능으로 인한 충돌 사고로 이어질 수 있습니다.도 피할 수 있는 모든 충돌할 수 있 품질 보증을 저장하는 선형 O(n)는 시간을 O(1)시간 최악의 경우에,여기서(n)은 수의 가능한 충돌(는 경우에,sparse matrix,할 수 있는 최대의 수를 기본값 셀의 행렬에서,즉최대 총 수의 크기의 행렬은 시간을 요인에 비례하는 해시 작성 요소에 대해 비 스파 스 즉전체 매트릭스).

RC(행 압축)기술에 사용되는 콜트는 가까이에서도,그러나 이것은 또 다른 가격에,여기에 압축 기술을 사용하는 것이 매우 느리게 액세스 시간에 대해 가장 자주 읽기만을 얻()작업,그리고 매우 느리에 대한 압축 setAt()작업입니다.또한,압축을 사용하지 않은 직각과는 달리,이 프리젠테이션의 시도는 직교성이 유지됩니다.하려고 것도 보존하이 직교성에 대한 관련 보과 같은 작업을 리딩,전위(으로 볼 월쯤 기반으로 작업을 정수를 주기적인 모듈 운영),subranging(및 subselections 에서 일반적인 포함하여 정렬 보기).

하는 나만 나귀 새끼에 업데이트됩니다 어떤 미래를 구현하는 다른 사용하여 구현하려고(즉TrieSparseMatrix 대 HashSparseMatrix 및 RCSparseMatrix).아이디어에서 이 문서입니다.

Trove 구현(에 기반 int->int 도)은 또한 해시를 기반으로 기술과 유사한 나귀 새끼의 HashedSparseMatrix,즉그들은 같은 불편합니다.하려고 많이 될 것입니다 더 빠르고,적당한 추가적인 공간을 소비하고(그러나 이 공간을 최적화할 수 있습이 될 것보다 더 나은 야와 나귀 새끼에서,지연시간을 사용하여,최종 콤팩트()이온은 작업에서 매트릭스/라).

참고:이 기술을 사용하여 구현합니다.네이티브 형식을 사용하여(여기에 두 번).이것은 자발적이기 때문에,일반적인 구현을 사용하여 복싱 유형에 거대한 공간이 있는 오버헤드(그리고 훨씬 더 느린에서 액세스 시간).여기에 그것은 단지 사용하여 기본 unidimensional 배열의 이중 보다는 오히려 일반적인 벡터입니다.하지만 그것은 확실히 가을 파악하는 일반적인 구현에 대한뿐만 아니라 시도...불행하게도,자바도 허용하지 않기를 일반적인 수업으로 모든 혜택의 기본 유형을 제외하고,작성하여 여러 구현(일반 객체에 대한 종류는 각각 기본형),봉사하는 이 모든 작업을 통해 공장을 타자를 치십시오.언어할 수 있어야를 자동으로 instanciate 기본 구현 및 빌드 공장 자동으로(지금은 그것이 아닌 경우에도 Java7 이것은 뭔가.순전히 유지는 이점에 대한 일반적인 유형으로 빠른 기본 유형으로).

다른 팁

Java Matrix 라이브러리를 테스트하기 위해 프레임 워크를 따라, 이들의 좋은 목록도 제공합니다!https://lessthanoptimal.github.io/java-matrix-benchmark/

테스트 된 라이브러리 :

* Colt
* Commons Math
* Efficient Java Matrix Library (EJML)
* Jama
* jblas
* JScience (Older benchmarks only)
* Matrix Toolkit Java (MTJ)
* OjAlgo
* Parallel Colt
* Universal Java Matrix Package (UJMP) 

이것은 간단한 것 같습니다.

Row*MaxColums+열을 인덱스로 사용하여 데이터의 이진 트리를 사용할 수 있습니다.

항목을 찾으려면 단순히 행*maxcolums+열 및 이진 검색을 찾고있는 트리를 검색하는 경우가 있으시면 NULL (NULL (LOG N)이 객체를 포함하는 셀 수입니다)를 반환 할 수 있습니다.

아마도 가장 빠른 런타임 솔루션은 아니지만 내가 생각해 볼 수있는 가장 빠른 런타임 솔루션은 작동하는 것 같습니다. 인덱스 클래스를 만들고 다음과 같은 SortedEdMap의 키로 사용하십시오.

    SortedMap<Index, Object> entries = new TreeMap<Index, Object>();
    entries.put(new Index(1, 4), "1-4");
    entries.put(new Index(5555555555l, 767777777777l), "5555555555l-767777777777l");
    System.out.println(entries.size());
    System.out.println(entries.get(new Index(1, 4)));
    System.out.println(entries.get(new Index(5555555555l, 767777777777l)));

내 인덱스 클래스는 다음과 같습니다 (Eclipse Code Generator의 도움으로).

public static class Index implements Comparable<Index>
{
    private long x;
    private long y;

    public Index(long x, long y)
    {
        super();
        this.x = x;
        this.y = y;
    }

    public int compareTo(Index index)
    {
        long ix = index.x;
        if (ix == x)
        {
            long iy = index.y;
            if (iy == y)
            {
                return 0;
            }
            else if (iy < y)
            {
                return -1;
            }
            else
            {
                return 1;
            }
        }
        else if (ix < x)
        {
            return -1;
        }
        else
        {
            return 1;
        }
    }

    public int hashCode()
    {
        final int PRIME = 31;
        int result = 1;
        result = PRIME * result + (int) (x ^ (x >>> 32));
        result = PRIME * result + (int) (y ^ (y >>> 32));
        return result;
    }

    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Index other = (Index) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }

    public long getX()
    {
        return x;
    }

    public long getY()
    {
        return y;
    }
}

당신은 Migth를 봅니다 LA4J (Java의 선형 대수) 라이브러리. 지원합니다 CRS (압축 행 저장) 만큼 잘 CCS (압축 열 저장) 희소 행렬에 대한 내부 표현. 따라서 이들은 희소 데이터를위한 가장 효율적이고 빠른 내부 혐의입니다.

다음은 희소 행렬을 사용하는 간단한 예입니다. LA4J:

Matrix a = new CRSMatrix(new double[][]{ // 'a' - CRS sparse matrix
   { 1.0, 0.0, 3.0 },
   { 0.0, 5.0, 0.0 },
   { 7.0, 0.0. 9.0 }
});

Matrix b = a.transpose(); // 'b' - CRS sparse matrix

Matrix c = b.multiply(a, Matrices.CCS_FACTORY); // 'c' = 'b' * 'a'; 
                                                // 'c' - CCS sparse matrix

당신이 사용할 수 있습니 중첩된 지도 있지만 경우에 당신이 할 필요가 매트릭스 수학에서 그것되지 않을 수도 있는 최고의 옵션

 Map<Integer, Map<integer, Object>> matrix;

어쩌면 대신 사용하는 개체의 몇 가지 튜플 위한 실제 데이터로 작업할 수 있도록 보다 쉽게 추출 후,다음과 같습니다.

class Tuple<T extends yourDataObject> {
  public final int x;
  public final int y;
  public final T object;
}

class Matrix {
  private final Map<Integer, Map<interger, Tupple>> data = new...;

 void add(int x, int y, Object object) {
     data.get(x).put(new Tupple(x,y,object);
 }
}


//etc

null 확인 등을 생략한

해시 맵 암석. stringbuilder ( + 또는 string.format)를 사용하여 분리기 (문자열)와 인덱스 (문자열로)를 연결하고 키로 사용하십시오. 그보다 더 빠르고 메모리 효율성이 높아질 수 없습니다. 드문 매트릭스는 20 세기입니다. :-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top