Сложный ключ для гуавы Кеш (сдвиг) - PullRequest
8 голосов
/ 23 ноября 2011

У меня есть точечный объект:

  class Point {
    final int x,y;
    ...
  }

Поскольку эти точки будут использоваться / создаваться повсеместно в моем коде, я хочу начать использовать кеш guavas. К сожалению, CacheLoader принимает только один параметр. Другой вопрос здесь, в stackoverflow, использовать объект пары для аналогичной проблемы. Но мне не нравится идея создания фиктивного объекта для каждого запроса кеша. Поэтому я придумаю свой собственный обходной путь:

Поскольку объект задан x и y, я думаю, что я могу объединить (сдвинуть) оба значения в long, который будет моим ключом.

void test(int x, int y) {
    Long key = (long) ((long) (x) << Integer.SIZE | y);
    Point point = cache.get(key);
}

CacheLoader<Long, Point> loader = new CacheLoader<Long, Point>() {
    public Point load(Long key) throws Exception {
    final int x,y;
        // shift magic
        x = (int) (key >> Integer.SIZE);
        y = key.intValue();
        return new Point(x, y);
    }
};

Я на самом деле новичок смены. Будет ли это работать? Я что-то пропустил? Это "быстрее", чем класс пары? Это мой вопрос!

Да, я тестирую код, и он пока работает, я могу сказать.

Ответы [ 2 ]

8 голосов
/ 23 ноября 2011

Как насчет этого? Ваш класс Point должен правильно реализовывать equals() и hashcode().

static class Points {
  static final Interner<Point> INTERNER = Interners.newStrongInterner();

  public static Point cached(final int x, final int y) {
    return INTERNER.intern(new Point(x, y));
  }
}

Ваша настоящая цель состояла в том, чтобы кэшировать равные объекты, верно? Чем этого будет достаточно для ваших нужд. Использование:

Point center = Points.cached(0, 0);

Или скорректированная версия вашего кеша:

CacheLoader<Point, Point> loader = new CacheLoader<Point, Point>() {
  @Override
  public Point load(final Point point) {
    return point;
  }
}
...
Point center = cache.get(new Point(0, 0));
3 голосов
/ 23 ноября 2011

Возможно, это быстрее (если разница вообще измерима), но класс пар сделает ваш код намного лучше для понимания или повторного использования Я бы пошел с общим классом Pair:

public final class Pair<L, R> {

    private final L left;
    private final R right;

    private Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public static <L,R>Pair<L,R> of(L left, R right){
        return new Pair<L, R>(left,right);
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof Pair) {
            final Pair<?,?> other = (Pair<?,?>) obj;
            return Objects.equal(left,  other.left)
                && Objects.equal(right, other.right);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(left, right);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                      .add("left", left)
                      .add("right", right)
                      .toString();
    }

}

Как только вы получите это в своей кодовой базе, вы найдете несколько вариантов его использования. Сдвиг битов в действительности не похож на Java (хотя многие другие не согласятся).

Документы Guava

...