2013-12-24 6 views
5

Я не думаю, что есть способ, который эффективен (если вообще) делать это, но я решил, что попрошу, если кто-то другой знает иначе. Я ищу, чтобы создать свою собственную таблицу кэша/поиска. Чтобы сделать его максимально полезным, я хотел бы, чтобы он мог хранить общие объекты. Проблема с этим подходом заключается в том, что даже если вы можете сделать Collections.unmodifiableMap, immutableMap, etc, эти реализации только мешают вам изменить Карту. Они не мешают вам получать ценность с карты и изменять ее базовые значения. По сути, мне нужно, чтобы что-то случилось с HashMap<K, ? extends Immutable>, но, насколько мне известно, ничего подобного не существует.Создайте hashmap неизменных общих объектов.

Я был первоначально думал, что я мог бы просто вернуть копию значений в кэше в методе GET, но так как интерфейс в Java Cloneable это козлы, вы можете не простой вызов

public V getItem(K key){ 
    return (V) map.get(k).clone(); 
} 
+0

Возможно, вы можете достичь этого с помощью некоторой библиотеки отражений, которая может выполнять глубокую копию объектов - это может быть полезно: http://stackoverflow.com/questions/2156120/java-recommended-solution-for-deep-cloning- copy-a-instance –

+0

Следует также добавить, что это должно быть эффективным. Я использую кеш для ускорения операций, и я бы не хотел потерять всю свою экономию от сжатия, чтобы сделать кучу отраженных хаков. – FuriousGeorge

+0

Я думаю, что лучший способ - пойти с неизменными объектами, как кто-то уже упоминал в одном из ответов. Я не знаю ни о каком хорошем методе в java, который может эффективно создавать глубокую копию объекта. Возможно, есть способ вернуть неизменный объект с AspectJ, но я не очень разбираюсь в этом, но, возможно, вы также можете найти решение. –

ответ

5

Ваше мышление хорошее, и вы правы, что нет встроенного способа обращения к неизменности.

Однако, вы можете попробовать это:

interface Copyable<T> { 
    T getCopy(); 
} 

Затем переопределить метод get() вернуть копии вместо самого значения;

class CopyMap<K, V extends Copyable<V>> extends HashMap<K, V> { 
    @Override 
    public V get(Object key) { 
     return super.get(key).getCopy(); 
    } 
} 

Тогда это до реализации, чтобы вернуть копию себя, а не this (если сам класс не является неизменным). Хотя вы не можете обеспечить это в коде, вы будете в пределах своих прав публично унижать программиста, который не соответствует.

+0

FYI Я добавил код, чтобы сделать эту идею безболезненной. – Bohemian

+0

Я думал об этом так. Я хотел бы иметь возможность принимать * любой * класс, но я думаю, это должно будет сделать. Это отчасти отстой, потому что теперь я не могу просто использовать такие классы, как «Текст», мне нужно их обернуть и/или расширить, а затем я столкнулся с проблемами производительности. – FuriousGeorge

+0

Я предлагаю иметь как изменяемые, так и неизменные объекты/интерфейсы из общего «читаемого» интерфейса, который включает в себя элементы 'asMutable',' asNewMutable' и 'asImmutable'. Если объекту нужен снимок чего-то, что он никогда не изменит, и если что-то еще может потребовать его для моментального снимка, он может также потребовать неизменный моментальный снимок, чтобы при запросе моментального снимка он мог просто вернуть ссылку к той, которую он уже имеет. – supercat

2

Я m для создания моей собственной таблицы кэша/поиска.

Почему бы не использовать Guava cache?

Проблема такого подхода заключается в том, что даже если вы можете сделать Collections.unmodifiableMap, immutableMap и т.д., эти реализации только мешают вам от изменения самой карты. Они не мешают вам получить значение с карты и изменить его базовые значения .

Это не что-то, что может обеспечить вас коллекция. Вам необходимо сделать классы себя неизменяемым. Там - это хакерский подход с использованием Reflection (который также можно использовать для преобразования класса!), Но на самом деле вам следует избегать этого и просто создавать классы, которые являются неизменными.

+0

Согласен, но я не создатель каждого класса. Например, я использую это с MapReduce, но я хочу иметь возможность хранить текстовые значения. Я бы предпочел не принимать штраф за создание новой строки для каждого значения Text, но в то же время я не могу сделать Text immutable – FuriousGeorge

1

Есть другие варианты для клонирования объектов в Java: Making a copy of an object Dynamically?

Помните только, что глубокое клонирование любой объект может быть опасным. Объекты, хранящиеся на этой карте, должны быть изолированы друг от друга, чтобы гарантировать, что весь объектный граф не будет скопирован при возврате одной записи.

+0

Это интересно, хотя, поскольку я хочу, чтобы он был общим, я знаю, могу ли я действительно рискнуть, что кромка края – FuriousGeorge

1

В языке нет формальной концепции «изменчивости» или «неизменности». Компилятор не может определить, является ли тип «изменчивым» или «неизменным».Чтобы определить, является ли что-то неизменным, мы, люди, должны изучать каждое поле и метод класса и рассуждать поведением методов, чтобы обнаружить, что ни один из них не изменит состояние объекта, тогда мы называем его «неизменным». Но нет никакого различия с точки зрения языка.

Смежные вопросы