2013-06-24 4 views
3

Я использую как Gson, так и Guava. У меня есть класс, который я хочу сериализации, который выглядит как что-то вроде этого sscceMultimap и gson performance

import com.google.common.collect.Multimap; 
public class FooManager { 
    private Multimap<String, Foo> managedFoos; 
    // other stuff 
} 

Gson не знает, как сериализовать это. Так что я сделал это:

public final class FoomapSerializer implements 
          JsonSerializer<Multimap<String, Foo>> { 
    @SuppressWarnings("serial") 
    private static final Type t = 
      new TypeToken<Map<String, Collection<Foo>>>() {}.getType(); 

    @Override 
    public JsonElement serialize(Multimap<String, Foo> arg0, Type arg1, 
     JsonSerializationContext arg2) { 
    return arg2.serialize(arg0.asMap(), t); 
    } 
} 

Однако, боюсь, вызывая .asMap() снова и снова будет медленным, даже если основной Map редко меняется. (Сериализация объектов Foo будет меняться часто, но само отображение не будет после инициализации). Есть ли способ лучше?

+2

Вы говорите, что боитесь этого; но вы приурочили его к альтернативным подходам, например, используя [суппорт] (https://code.google.com/p/caliper/)? Кроме того, вы пробовали Джексона? – fge

+0

Я не приурочил его к альтернативным подходам, но я сделал это время против себя; Другими словами, я сравнивал вызов 'asMap' несколько раз на одной карте с' asMap' на разных дублированных картах с теми же данными, и одна и та же карта была не намного быстрее. Мой тест суппорта, возможно, был плохим, хотя. – durron597

+0

Кроме того, все, что я читал, говорит о том, что Джексон был быстрее 2-3 года назад, но теперь он быстрее. – durron597

ответ

7

Multimap.asMap возвращает кешированный вид Multimap в O (1) раз. Это не дорогостоящая операция. (На самом деле, это довольно дешево, требуя не более одного распределения.)

3

Вот пример универсального сериализатора для мультикадров с использованием Guava TypeToken. Есть несколько вариантов этого, что вы могли бы сделать, если хотите, например, создание экземпляров сериализатора для каждого типа мультимапа, который вам нужно сериализовать, поэтому вам нужно только один раз разрешить возвращаемый тип asMap().

public enum MultimapSerializer implements JsonSerializer<Multimap<?, ?>> { 
    INSTANCE; 

    private static final Type asMapReturnType = getAsMapMethod() 
     .getGenericReturnType(); 

    @Override 
    public JsonElement serialize(Multimap<?, ?> multimap, Type multimapType, 
     JsonSerializationContext context) { 
    return context.serialize(multimap.asMap(), asMapType(multimapType)); 
    } 

    private static Type asMapType(Type multimapType) { 
    return TypeToken.of(multimapType).resolveType(asMapReturnType).getType(); 
    } 

    private static Method getAsMapMethod() { 
    try { 
     return Multimap.class.getDeclaredMethod("asMap"); 
    } catch (NoSuchMethodException e) { 
     throw new AssertionError(e); 
    } 
    } 
} 
+0

Увлекательный, я никогда не видел, чтобы переименование использовалось таким образом. Это просто сокращение для singleton? Если я использую Guice '@ Singleton', это не обязательно делать так, верно? – durron597

+0

@ durron597: Да, это шаблон однолучевого переименования, рекомендованный Джошем Блохом в «Эффективной Java_» для таких вещей. Хотя жесткие синглтоны часто представляют собой плохую идею, и использование Guice для охвата объекта в качестве одноэлементного, как правило, является лучшей идеей, это не тот тип объекта, который я бы рассматривал с помощью Guice. Это легкий, не имеющий аналогов функциональный объект, и я просто использую его непосредственно при регистрации адаптеров типов с Gson. – ColinD