Почему коллекционные литералы? - PullRequest
27 голосов
/ 23 апреля 2010

Из различных онлайн-статей о Java 7 я узнал, что Java 7 будет иметь коллекционные литералы 1 , например:

List<String> fruits = [ "Apple", "Mango", "Guava" ];
Set<String> flowers = { "Rose", "Daisy", "Chrysanthemum" };
Map<Integer, String> hindiNums = { 1 : "Ek", 2 : "Do", 3 : "Teen" }; 

Мои вопросы:

  1. Не было бы возможно обеспечить статический метод of во всех классах коллекций, которые можно использовать следующим образом:

List<String> fruits = ArrayList.of("Apple", "Mango", "Guava");

IMO, это выглядит так же хорошо, как и буквальная версия, и также достаточно кратко. Почему тогда они должны были изобрести новый синтаксис ( РЕДАКТИРОВАТЬ: Под «новым» я имею в виду «новый для Java».)?

  1. Когда я говорю List<String> fruits = [ "Apple", "Mango", "Guava" ];, что List я на самом деле получу? Это будет ArrayList или LinkedList или что-то еще?

1 Как отмечалось в комментариях, литералы коллекции не сделали разрез для Java 7, да и для Java 8. (Вот письмо от Брайана Гетц, разработчик Oracle, резюмирует причины, по которым эта функция не включена, и вот собственно предложение .)

Ответы [ 11 ]

11 голосов
/ 23 апреля 2010

Ответ на вопрос 2:

final List<Integer> piDigits = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9];

дает вам неизменный список.

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

Прочтите подробности здесь: Предложение: литералы коллекции

Ответ на вопрос 1: да, это так. Это вопрос стиля.

7 голосов
/ 23 апреля 2010

Еще одна вещь, на которую стоит обратить внимание, это то, что для списков это очень легко использовать с помощью ar args, но немного подумайте, как бы вы сделали это для карты. Невозможно предоставить пары аргументов методу var args, если вы не введете дополнительный объект Map.Entry или что-то в этом роде.

Таким образом, используя существующий синтаксис, вы получите

Map<String,String> map = HashMap.of( new Entry( "key1", "value1" ), 
                                     new Entry( "key2", "value2" ) );

, что очень быстро утомляет.

Даже если вы идете по пути использования паттерна строителя (как мы делаем), это довольно уродливо

Map<String,String> map = CollectionUtil.<String,String>map()
                                        .put( "key1", "value1" )
                                        .put( "key2", "value2" )
                                        .map();
4 голосов
/ 31 марта 2011

Не упоминается выше простота коллекций коллекций.Допустим, вы хотите, чтобы константа хранила названия и значения валют разных стран.

// Currency devisions by country, and their various names
Map<String,Map<Float,List<String>>> CURRENCIES =
    { "US" : { 1 : ["dollar","buck"],
               0.25 : ["quarter"],
               0.10 : ["dime"],
               0.05 : ["nickel"],
               0.01 : ["penny"] },
      "UK" : { 1 : ["pound"],
               1.05 ["guinea"],
               0.125 : ["half crown"],
               0.05 : ["shilling","bob"],
               0.025 : ["sixpence"] } 
    };

Я упаковал огромное количество данных в двенадцать чрезвычайно четких строк.Если бы я использовал ArrayList.of (десять раз) и какой-то аналогичный конструктор карт (четыре раза, с десятью Map.EntryPair!), Вызовы функций раздуты и сделали бы код значительно труднее для чтения.

Хотяэто определенно относится к области синтаксического сахара, это функция # 1, которую я с нетерпением жду в Java 7 (если она когда-нибудь выйдет).

3 голосов
/ 23 апреля 2010

A1 Да, это возможно, но требует, чтобы вы печатали все больше и больше.

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

По мере того, как аппаратное обеспечение становилось все быстрее, новые языки программирования, которые вначале были слишком дороги для выполнения вычислений, стали возможными, и теперь они используются все больше и больше и очень популярны. Когда разработчикам приходится снова печатать на Java, они чувствуют, что-то вроде о нет: , public static void main снова! .

Одна из вещей, которая была необходима Java (и статически типизированным языкам в целом) для увеличения скорости выполнения, - это выполнение максимально возможного количества проверок до запуска (то есть на этапе компиляции)

Эти новые языки программирования (особенно Python и Ruby) доставляют удовольствие от программирования, потому что вам нужно меньше печатать, чтобы достичь того же.

Реакция Java на это заключается в том, чтобы сделать язык больше и включить в него часть этого "синтаксического сахара", вот почему.

Даже языки программирования, такие как C #, имели эти расширенные функции (мне приходят в голову свойства), чтобы сделать код разработчика меньше.

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

Я думаю, что альтернативой было бы сделать методы более выразительными в своих именах, но это очень сложно для Java. Возможно на новом языке :).

Подпись метода Map put могла выглядеть так:

 /**
  * Analog to put( Object k, Object v );
  */
 public [( Object = k )]=( Object  v ) {
 } 

Это позволяет имени метода быть: [(key)]=(value) и, в конце концов, пропустить круглые скобки (как в Ruby или первоначально в Smalltalk), так что этот метод будет:

 Map map = ....
 map.["name"]="Oscar";

Поскольку это невозможно (потому что []= не являются допустимыми идентификаторами методов) и запись:

 map.put("name","Oscar");

Это ... ммхх слишком многословно, они решили добавить это решение.

Еще одним улучшением являются числовые литералы, поэтому вы сможете ввести:

 int million = 1_000_000;

A2 : Вы получите что-то еще.

A3 (расширение моего комментария к kloffy answer).

Вы можете написать тот же код на Java на сегодняшний день.

Предоставлено Stage, Scente, Group, Text, ImageView, Image существующие классы Java, вы можете набрать:

 new Stage() {{
     title  =  "Group-Nodes-Transformation";
     scene  =  new Scene() {{
         width =  600;
         height = 600;
         content = new Group() {{
             content = new Object[] =  {
                 new Circle() {{
                     centerX = 300;
                     centerY = 300;
                     radius = 250;
                     fill = Color.WHITE;
                     stroke = Color.BLACK;
                 }},
                 new Text() {{
                     x = 300;
                     y = 300;
                     content = "Mr. Duke";
                 }},
                 new ImageView() {{
                     image = new  Image() {{
                         url = "D:\\TEST\\Documents\\duke.png"
                         width = 50;
                         height = 50;
                     }};
                 }};
             };
         }};
     }};
 }};
2 голосов
/ 23 апреля 2010

Возможно, они были вдохновлены декларативным стилем программирования JavaFX . Однако, если это так, я разочарован тем, что они не полностью поддержали литералы объектов. Вот пример объектных литералов в JavaFX:

Stage {
    title: "Group-Nodes-Transformation"
    scene: Scene {
        width: 600
        height: 600
        content: Group {
            content: [
                Circle {
                    centerX: 300
                    centerY: 300
                    radius: 250
                    fill: Color.WHITE
                    stroke: Color.BLACK
                },
                Text {
                    x: 300
                    y: 300
                    content: "Mr. Duke"
                },
                ImageView {
                    image: Image {
                        url: "D:\\TEST\\Documents\\duke.png"
                        width:50
                        height:50
                    }
                }
            ]
        }
    }
}

Я думаю, что этот стиль программирования определенно пригоден для определенных областей применения. В конце концов, это всегда вопрос вкуса ...

1 голос
/ 23 апреля 2010

IMO это просто синтаксический сахар , который немного упрощает код. Почему вас не удивляет сахар такого же типа:

int []arr1 = new int[] {1,2,3};
int []arr2 = {1,2,3};

Это просто удобный способ выразить простую идею вместо того, чтобы писать что-то вроде

int []arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

Это добавляет что-то действительно новое в нашу жизнь? Ну нет. Делает ли это нашу жизнь немного проще? Я думаю, да.

Относительно второй части вопроса, я не знаю, какими будут настоящие типы. Но, честно говоря, как часто вы заботитесь о том, что такое реализация коллекции? Особенно с учетом того, что такие коллекции должны быть относительно небольшими (со всеми значениями, набранными разработчиком). В любом случае, в тех редких случаях, когда вам все равно, просто не используйте этот упрощенный синтаксис и выполняйте работу самостоятельно.

1 голос
/ 23 апреля 2010

Язык дизайна - дело вкуса. Сказав это, этот вид инициализации списка / объекта стал очень популярным. Например, в C # есть почти то же самое. Синтаксис достаточно гибкий и, как показывают ваши примеры, позволяет инициализировать что-то вроде встроенного словаря. Мне скорее нравится синтаксис, который дизайнеры выбрали здесь.

0 голосов
/ 23 апреля 2010

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

Причина, по которой ... расширяется до массива java, а массивы java не любят общие экземпляры.

Вот пример из спецификации, которая касается этой конкретной проблемы:

List<List<Integer>> pascalsTriangle =
    [[1],
     [1, 1],
     [1, 2, 1],
     [1, 3, 3, 1],
     [1, 4, 6, 4, 1]]

В настоящее время нет способа инициализировать эту переменную таким кратким образом и без непроверенного предупреждения.

0 голосов
/ 23 апреля 2010

Вы правы, это просто пустой синтаксический сахар.

Также ваша ArrayList.of(...) будет просто короткой рукой для new ArrayList<...>(Arrays.asList(...))

0 голосов
/ 23 апреля 2010

Это не совсем новый синтаксис, поскольку такие литералы присутствуют в Python, Javascript (json) и, возможно, других языках.

Я не видел никакой информации о java 7, которая была бы откровенной (в последнее время она была сосредоточена на C ++ и Javascript), но на самом деле приятно видеть такое дополнение к языку.

...