2013-11-01 5 views
6

Я использую Apache Avro.Apache Avro: карта использует CharSequence как ключ

Моя схема имеет тип карты:

{"name": "MyData", 
    "type" : {"type": "map", 
       "values":{ 
        "type": "record", 
        "name": "Person", 
        "fields":[ 
         {"name": "name", "type": "string"}, 
         {"name": "age", "type": "int"}, 

       ] 
       } 
       } 
} 

После компиляции схемы, то genated использование класса Java CharSequence как ключа для MapMyData.

Это очень неудобно использовать CharSequence в Map в качестве ключа, есть способ создания String ключа типа для Map в Apache Avro?

P.S.

Проблема заключается в том, что, например dataMap.containsKey("SOME_KEY") будет возвращает false, даже если есть такой ключ есть, только потому, что это CharSequence. Кроме того, поместить запись в карту с существующим ключом, не переместить старый. Вот почему я говорю, что неудобно использовать CharSequence в качестве ключа.

+0

С учетом вашего ответа на один ответ: вы узнали, что именно для вас нарушает? Как и в самом деле, действительно ли «Карта» использует клавиши, отличные от 'String'? – millimoose

+0

Millimoose, сгенерированное использование карты CharSequence для ключа. – Mellon

+0

Сгенерированная карта по умолчанию использует Utf8, и вы можете выбрать ее для String. CharSequence - это просто интерфейс. –

ответ

2

Независимо от того, можно ли заставить Avro использовать String, используя CharSequence непосредственно плохая реализация, так как CharSequence не Comparable<CharSequence> и даже не указать равенство двух одинаковых последовательностей. Я предлагаю подать это как ошибку против Avro.

+0

Фактически даже в довольно тривиальном случае ('String' и' StringBuilder') хэш-коды не соответствуют: http://ideone.com/cX76YN. (Они делают для 'StringBuffer' и' StringBuilder', но это, вероятно, является последствием последнего, являющегося в основном копией первого с удалением синхронизации.) – millimoose

+0

@millimoose 'StringBuffer' и' StringBuilder' расширяют защищенный пакетом 'AbstractStringBuilder' поэтому не удивительно, что они действуют одинаково. Согласитесь, что это проблема реализации. –

3

По-видимому, по умолчанию, Avro использует CharSequence. Я нашел a way to configure it to convert to String

Начиная с версии Avro 1.6.0, существует возможность, чтобы Avro всегда выполнял преобразование в String. Есть несколько способов добиться этого. Во-первых, чтобы установить avro.java.string свойство в схеме в строку:

  { "type": "string", "avro.java.string": "String" } 

Я не проверял это.

+0

Это правильный способ сделать это, и это свойство присутствует, чтобы справиться с этой точной проблемой. –

+0

- это конфигурация каждого поля? как вы это делаете для ключа карты? также, ссылка мертва. – andresp

6

Видимо, есть обходной путь для этой проблемы в Avro 1.6. Необходимо указать тип строки в файле POM вашего проекта:

<stringType>String</stringType> 

Это упоминается в этом вопросе AVRO-803 ... хотя веб-документация плагина не отражает это.

+0

В соответствии с этим вопросом, чтобы добавить оскорбление к травме, используемый подкласс 'CharSequence' на самом деле является классом, специфичным для Avro (' Utf8'), который они могли бы легко сделать hashable/equatable для 'String', чтобы уменьшить часть боли. – millimoose

+0

Это хороший момент. Это может быть целесообразным изменением для Avro, если оно еще не добавлено. С другой стороны, CharSequence не гарантирует поведение равенства, поэтому, возможно, в любом случае лучше использовать toString(). –

6

This JIRA discussion имеет отношение к делу. Основной момент использования CharSequence - - обратная совместимость.

И, как заметил Чарльз Форсайт, было добавлено обходное решение для того, когда требуется String, установив свойство string в схеме.

{ "type": "string", "avro.java.string": "String" } 

Тип по умолчанию - это их собственный класс Utf8.В дополнение к ручному спецификации и the pom.xml setting, есть даже Avro-инструменты компиляции опции для этого, -string вариант:

java -jar avro-tools.1.7.5.jar compile -string schema /path/to/schema . 
0

быстрое решение (тип значения могут быть и другие объекты, теперь я):

Map<String, String> convertToStringMap(Map<CharSequence, CharSequence> map){ 
    if (null == map){ 
     return null; 
    } 
    HashMap<String, String> result = new HashMap<String, String>(); 
    for(CharSequence key: map.keySet()){ 
     CharSequence k_value = map.get(key); 
     String s_key = key.toString(); 
     String s_value = k_value.toString(); 
     result.put(s_key, s_value); 
    } 
    return result; 
} 
0

Я думаю, что явное преобразование String в Utf8 будет работать. «some_key» -> новый Utf8 («some_key») и используйте это как свой ключ для карты.

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