Почему SparseArray не совместим с Android JFC?

Итак, я должен использовать SparseArray вместо HashMap ради производительности:

Однако SparseArray не является частью JCF и не реализует Collection или List или Map. HashMap, с другой стороны, реализует < a href="http://docs.oracle.com/javase/6/docs/api/java/util/Map.html" rel="nofollow">Map и предоставляет values(), с которыми я могу работать, когда мне нужно JCF-совместимое поведение. Например, используя его в ArrayAdapter и различной пользовательской сортировке (для значений ).

Мой вопрос состоит из трех частей:

  1. Почему SparseArray не реализует JCF интерфейсы? Я имею в виду, какова мотивация не реализовывать эти интерфейсы в свете того факта, что большинство методов уже есть?
  2. Существуют ли альтернативы SparseArray, реализующие JCF или могут быть легко преобразованы с сохранением SparseArray производительность?
  3. На самом деле HashMap с несколькими сотнями элементов настолько медленнее? Действительно ли мои пользователи это заметят?

Я ищу подробные ответы и предпочитаю ссылки на авторитетные сайты. Если вы думаете, что знаете, почему SparseArray не был реализован с интерфейсами JCF, покажите некоторая поддержка, помогите мне понять. Если вы считаете, что мне следует использовать SparseArray, покажите мне, как его использовать. с ArrayAdapter и настраиваемой сортировкой (рекомендуются решения Comparator). Если есть лучшие альтернативы, были бы полезны ссылки на документ API, библиотеку или учебник. Если вы считаете, что мне следует придерживаться HashMaps , объясните, почему преимущества производительности SparseArray перевешиваются потребностями интерфейсы.


person mawcsco    schedule 19.04.2013    source источник
comment
Действительно ли HashMaps с несколькими сотнями элементов намного медленнее? Действительно ли мои пользователи это заметят? -- Когда вы создали свой бенчмарк и запустили тесты, особенно с использованием таких инструментов, как Traceview, чему вы научились?   -  person CommonsWare    schedule 23.04.2013
comment
@CommonsWare Я никогда не создавал тест. Зачем мне это делать? Я создаю приложение, а не тестирую производительность коллекций. Я запускал Traceview, но не могу сказать, хорошо это или плохо. Все работает нормально. Мне не с чем его сравнивать, потому что я никогда не создавал его с помощью SparseArray. На самом деле, нет никакого практического способа сделать это. Все, что мне нужно сделать, это предупреждения Lint, говорящие мне, что я должен использовать SparseArray. Я игнорирую эти предупреждения? Трачу ли я время на полный рефакторинг своего кода?   -  person mawcsco    schedule 23.04.2013
comment
Зачем мне это делать? -- чтобы ответить на вопросы: действительно ли HashMaps с несколькими сотнями элементов намного медленнее? Действительно ли мои пользователи это заметят? Никто другой не сможет ответить на этот вопрос, поскольку мы понятия не имеем, как, где и когда вы используете HashMap. На самом деле, нет никакого практического способа сделать это — поскольку вы единственный человек на планете, который знает ваше приложение, нам придется принять это за чистую монету. Я игнорирую эти предупреждения? -- если нет практического способа использовать SparseArray, у вас, похоже, нет выбора.   -  person CommonsWare    schedule 23.04.2013
comment
@CommonsWare Создание эталона предполагает, что у меня есть точка отсчета для сравнения. У меня этого нет. Я не использую SparseArray, потому что мне нужно использовать эти данные с ArrayAdapter, и мне нужна пользовательская сортировка (в настоящее время реализуется с помощью Comparator и Collections.sort()). Итак, мой первоначальный вопрос заключается в том, почему SparseArray реализован таким образом. И, поскольку это так, как мне справиться с этим предупреждением Lint.   -  person mawcsco    schedule 23.04.2013
comment
Тогда как вы ожидаете, что кто-то сможет ответить на вопрос № 3? Если вы не знаете, что они намного медленнее, как мы можем?   -  person CommonsWare    schedule 23.04.2013
comment
Если вы (коллективно) не можете ответить на № 3, то почему это рекомендуется? Очевидно, кто-то знает, что SparseArray — более производительная коллекция. Ясно, что у кого-то есть данные, полученные в результате многократного столкновения с проблемой, и они могут с уверенностью сказать, что мне следует использовать SparseArray. Очевидно, они добавили рекомендацию в Lint Rules в ADK. Единственные данные, которые я нашел, слишком расплывчаты, чтобы определить, повлияет ли этот прирост производительности на небольшие коллекции. Мне нужен авторитетный ответ от кого-то, кто много работает с SparseArray, чтобы помочь мне найти больше/лучших данных, прежде чем я приму важное решение.   -  person mawcsco    schedule 23.04.2013
comment
Если вы (коллективно) не можете ответить на № 3, то почему это рекомендуется? -- это предложено Lint как то, что вы могли бы рассмотреть. Lint — это не движок ИИ; некоторые из рекомендаций, которые он дает, будут неуместны для вашей конкретной ситуации. Мне нужен авторитетный ответ от кого-то, кто имеет большой опыт работы с SparseArray, чтобы помочь мне найти больше/более качественные данные, прежде чем я приму важное решение — вы поняли это в комментарии от fadden (инженер по Android).   -  person CommonsWare    schedule 23.04.2013
comment
Если у вас есть HashMap<Integer, Object>, рассмотрите SparseArray. Если его использование будет болезненным, используйте Traceview, чтобы определить, сколько времени вы тратите на свое нынешнее решение на основе HashMap. Если ответ не сильно, то по определению SparseArray поможет меньше, чем мало, и переживать не стоит. Что касается предупреждения о Lint, если вы решите придерживаться HashMap, должна быть аннотация @SuppressLint, которая заблокирует предупреждение. Если вы используете Eclipse, эта аннотация должна быть в списке быстрых исправлений (если нет, это ошибка ADT).   -  person CommonsWare    schedule 23.04.2013
comment
С точки зрения производительности также полезно подумать о дополнительных выделениях, которые, вероятно, потребуются упакованным целым числам. Здесь есть отличная презентация пары ребят из IBM: cs.virginia.edu/kim/publicity/pldi09tutorials/   -  person fadden    schedule 23.04.2013


Ответы (2)


Первая версия SparseArray.java была написана в мае 2006 года. В некотором смысле она предшествовала различным интерфейсам коллекций, о которых вы говорите (в Android, а не в Java). Я считаю, что он не поддерживает различные интерфейсы JCF, потому что они не существовали во время написания кода, и с тех пор никто не нашел причин их добавлять. (Он даже не использовал дженерики до начала 2007 года.)

Если вы считаете, что расширенный массив SparseArray полезен, всегда приветствуются высококачественные исправления.

person fadden    schedule 23.04.2013

Может быть, потому что это Map ‹ Object, Object>, но SparseArray имеет примитивные ключи.

Альтернатива — карта, как это было раньше

Для 3 в общем то да, но надо мерить и смотреть правда ли это в его случае

person Alexander Kulyakhtin    schedule 19.04.2013
comment
Снижает ли производительность автоматическая распаковка Map‹Integer, Object›? Как насчет интерфейса списка? - person mawcsco; 19.04.2013
comment
В Java Puzzlers amazon.com/Java-Puzzlers-Traps-Pitfalls -Corner/dp/032133678X, если я не ошибаюсь, объясняется, что упаковка-распаковка сильно влияет на производительность. Я могу ошибаться в этом, но лучше проверить - person Alexander Kulyakhtin; 19.04.2013
comment
Можете ли вы подробнее рассказать о своем ответе? # 1 Я хотел бы знать больше, чем «может быть» (я также могу предположить, что «может быть»). Я ищу веские причины, по которым JCF не был реализован. # 2 Я ищу альтернативы решению, которое у меня уже есть. # 3 Я не могу переключиться на SparseArray, не переписав полностью большую часть своего кода, поэтому у меня нет практического способа его измерить. Все, что я нашел по этому вопросу, это одна статья, на которую я дал ссылку. Мне нужно больше информации, а не больше предположений. - person mawcsco; 22.04.2013
comment
Нет, может быть. Это указано в документах: оно должно быть более эффективным, чем использование HashMap для сопоставления целых чисел с объектами. Избегание постоянной упаковки и распаковки Integer является причиной его существования. FWIW, другая забавная часть SparseArray заключается в том, что он реализует Cloneable, но его clone() не возвращает Object, что делает его ковариантным методом, а не перегрузкой. - person fadden; 23.04.2013
comment
@fadden Избегание постоянной упаковки и распаковки Integer является причиной его существования. Мне это не совсем понятно. Однако, если предположить, что это правда, это только объясняет, почему он не реализует Map‹K, V›. Как насчет Collection‹E› (или любого допустимого подинтерфейса), где E — тип значения? - person mawcsco; 23.04.2013
comment
@mawcsco: Collection<E> требует, чтобы метод add() принимал одно значение. SparseArray требуются ключи. - person CommonsWare; 23.04.2013
comment
@CommonsWare руководство JCF позволяет не реализовывать некоторые методы. Из документа Collection API: ... методы, которые изменяют коллекцию, с которой они работают, указываются для исключения исключения UnsupportedOperationException, если эта коллекция не поддерживает операцию. - person mawcsco; 23.04.2013
comment
@mawcsco: первая версия SparseArray.java была написана в мае 2006 года. В некотором смысле она предшествовала различным интерфейсам коллекций, о которых вы говорите (в Android, а не в Java). Я считаю, что он не поддерживает различные интерфейсы JCF, потому что они не существовали во время написания кода, и с тех пор никто не нашел причин их добавлять. (До начала 2007 года он даже не использовал дженерики.) Если вы сочтете это полезным, всегда приветствуются высококачественные исправления. - person fadden; 23.04.2013
comment
@fadden Это выдающаяся информация. Не могли бы вы поместить это в ответ вместо комментария. Я отмечу это как ответ. - person mawcsco; 23.04.2013