Лучше использовать список пар или два списка? - PullRequest
6 голосов
/ 22 сентября 2009

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

Я колеблюсь между реализацией этого как List<Pair<Integer, Integer>> или просто двумя List<Integer> аргументами. Оба, очевидно, будут работать , и ни один из них не вызовет проблем с реализацией или эффективностью в моем методе. В любом случае это в основном одна и та же информация (массив 2xn ), только чередующиеся по-разному.

Так что я хотел бы высказать несколько мнений о том, какое из них, по вашему мнению, будет лучше, и почему.

Преимущества списка пар, которые я вижу до сих пор:

  • Более точно отражает фактические отношения между сущностями
  • Устраняет некоторые классы динамических ошибок (например, несоответствующие длины списка)

Преимущества для пары списков:

  • Не полагается ни на какие классы, не относящиеся к JDK (просто, как Pair - концепция)
  • Не требует строительства каких-либо вспомогательных объектов только для переноса данных вокруг
  • В любом случае, вызывающие абоненты чаще имеют аргументы в отдельных списках, поэтому им не нужно перестраивать данные перед вызовом метода

Оба случая имеют одинаковую безопасность типов, а также одинаковую возможность несоответствия аргументов (например, ввод значений первым и идентификаторов секунд, когда это должно быть наоборот). Эту последнюю проблему можно избежать, создав тривиальную обертку вокруг Integer, называемую чем-то вроде PrimaryKey, которая имеет свои плюсы и минусы и в любом случае ортогональна этой проблеме, так как ее можно использовать одинаково в обоих случаях.

Тем не менее, существует золотая середина, которая может быть третьей опцией - тривиальный контейнерный класс с целочисленными полями для objectId и value. Это не требует помощи компилятора в обеспечении правильности объектов посредством ввода, но обеспечивает дополнительный уровень безопасности в назначениях. Я не думаю, что я бы пошел на это, так как мне не нравится идея загрязнения публичного интерфейса таким тривиальным классом, как этот.

Ответы [ 11 ]

23 голосов
/ 22 сентября 2009

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

Хранение двух списков в отдельности будет болезненным. Вы должны будете передать их вместе и синхронизировать их. Затраты на создание нового объекта для этого незначительны, и именно для этого предназначен ООП (вы будете создавать классы не-JDK, просто написав новый код Java для своего приложения, не забывайте).

Я все время создаю второстепенные классы. Они обеспечивают строгую безопасность типов и предоставляют возможности для улучшения и рефакторинга. IDE могут легче идентифицировать и выполнять рефакторинг.

5 голосов
/ 22 сентября 2009

Почему бы не использовать Словарь (тип карты, как бы она ни называлась в настоящее время в Java, я думаю, что раньше она была Hashtable)? Это позволит сопоставить идентификаторы со значениями и обойти вашу дилемму.

5 голосов
/ 22 сентября 2009

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

Я бы также склонялся к использованию класса Pair, ссылаясь на перечисленные вами преимущества:

  • Более точно отражает фактическое отношения между сущностями
  • Устраняет некоторые классы динамических ошибка (например, несоответствие длины списка)

Большой для меня был бы лучшим.

Всегда пишите код, который демонстрирует намерение. Не кодируйте, думая исключительно о реализации.

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

2 голосов
/ 22 сентября 2009

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

Если у вас есть миллионы этих пар, и потребление памяти становится основным , вы можете переключиться на пары списков (так как будет на один объект меньше за пару).

2 голосов
/ 22 сентября 2009

Я бы пошел за List из Pair с, если два целых числа действительно принадлежат друг другу и должны представлять "одну вещь".

Другим недостатком использования двух отдельных списков является то, что компилятор не проверяет вас, всегда ли списки имеют одинаковый размер. И вы оставляете интерпретацию клиенту вашего метода; клиент должен сопоставить элементы в двух списках.

Я не вижу использования такого класса, как Pair, как большого недостатка, "поскольку он опирается на классы не из JDK", как вы говорите, но если вы действительно не хотите использовать что-то вроде Pair Вы даже можете сделать это списком массивов: List<Integer[]>, где каждый массив содержит два объекта Integer. (На мой взгляд, это хуже, чем использовать Pair).

2 голосов
/ 22 сентября 2009

Когда API общедоступен, убедитесь, что вы просто реализуете основные функции, потому что все, что вы даете клиенту, никогда не может быть взято обратно.

Подумайте о методе с двумя назначенными параметрами (Integer entityId, Integer someOtherId) и дайте клиенту понять, как добавить больше элементов.

Если вы хотите разрешить удобный доступ, предоставьте им класс util, который поставляется с интерфейсом «Назначение», который просто определяет getEntityId () и getSomeOtherId (), и с реализацией по умолчанию, такой как DefaultAssignment, которая содержит окончательные ссылки на идентификаторы.

Тогда ваши клиенты могут выбрать, каким путем они хотят идти, и вам не нужно обязательно поддерживать ваш класс "Pair".

1 голос
/ 22 сентября 2009

Я наполовину не согласен с этим пунктом:

  • Не полагается ни на какие классы, не относящиеся к JDK (просто, как пара понимает как концепцию)

потому что, хотя в JDK нет класса Pair, есть интерфейс: Map.Entry, который соответствует вашему предполагаемому использованию в качестве ассоциации ключ / значение.

0 голосов
/ 22 сентября 2009

Возможно, вы захотите сделать параметр Iterator<Pair>. Если вызывающий класс имеет List<Pair>, получение итератора тривиально. Если нет, то создание итератора может быть легче построить, быстрее и / или более естественным. В некоторых случаях это может даже помочь вам устранить проблемы нехватки памяти.

0 голосов
/ 22 сентября 2009

Сначала напишите модульные тесты. Тогда вы легко сможете увидеть, с чем проще всего работать, а затем выберите это в качестве своей реализации.

0 голосов
/ 22 сентября 2009

Перейдите со списком пар или картой.

Я не покупаю ни одного из аргументов "против", которые вы перечислили.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...