为什么收集文字?

时间:2010-04-23 17:48:49

标签: java collections java-7

从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,可以按如下方式使用:
  2. List<String> fruits = ArrayList.of("Apple", "Mango", "Guava");

    IMO看起来和文字版一样好,而且也相当简洁。那为什么他们必须发明一种新的语法(编辑:按'新'我的意思是'刚接触Java'。)?

    1. 当我说List<String> fruits = [ "Apple", "Mango", "Guava" ];我真正得到List时会是什么?会是ArrayList还是LinkedList还是其他什么?

    2. 1 正如评论中所提到的,集合文字确实为Java 7做了切割,也没有做到Java 8.(这是来自Brian的email Goetz,Oracle开发人员,总结了不包括此功能的基本原理;这里是proposal本身。)

11 个答案:

答案 0 :(得分:11)

回答问题2:

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

为您提供不可变列表。

此提案的整个想法是无法指定子类型 。编译器根据右侧的集合选择合适的实现。

请在此处阅读详细信息:Proposal: Collection Literals

回答问题1:是的,它会有。这是一种风格问题。

答案 1 :(得分:7)

另外需要注意的是,对于列表来说,使用var args非常容易,但是想一想你是如何为地图做的。除非你引入一个额外的Map.Entry对象或类似的东西,否则无法为var args方法提供参数对。

因此,使用现有语法,您最终会使用

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();

答案 2 :(得分:4)

上面没有提到集合集合的简单性。假设您希望常量来存储不同国家/地区的货币名称和值。

// 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"] } 
    };

我已经在12条非常清晰的行中收集了大量数据。如果我使用ArrayList.of(十次)和一些类似的地图构造函数(四次,有十个Map.EntryPair!),函数调用会使代码膨胀并使其更难以阅读。

虽然它肯定属于语法糖的领域,但这是我在Java 7中期待的第一个功能(如果它已经发布)。

答案 3 :(得分:3)

A1 是的,但是要求您输入越来越多的内容。

虽然这肯定不是什么错误,但这是开发人员抱怨的事情之一。他们(有时我自己做)会觉得Java is too verbose

随着硬件变得越来越快,新的编程语言在开始时太昂贵而无法执行计算变得可行,并且它们现在被越来越多地使用并且非常受欢迎。当开发人员必须再次输入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回答的评论)。

你可以用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;
                     }};
                 }};
             };
         }};
     }};
 }};

答案 4 :(得分:2)

他们可能受到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
                    }
                }
            ]
        }
    }
}

我认为这种编程方式肯定适用于某些应用领域。最后,这总是一个品味问题......

答案 5 :(得分:1)

语言设计是一种品味问题。话虽如此,这种列表/对象初始化已经变得非常流行。例如,C#几乎完全相同。语法非常灵活,正如您的示例所示,可以让您初始化类似内联字典的内容。我更喜欢设计师在这里选择的语法。

答案 6 :(得分:1)

IMO这只是一个Syntactic sugar,可以简化代码。为什么你不会对同类糖感到惊讶:

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;

这是否为我们的生活增添了一些新东西?好吧,不。它会让我们的生活更轻松吗?我想,是的。

关于问题的第二部分,我不知道实际的类型是什么。但坦率地说,你经常关心什么是集合实现?特别是考虑到这些集合预计相对较小(所有值都由开发人员键入)。无论如何,在您关心的极少数情况下,请不要使用这种简化的语法并自己完成工作。

答案 7 :(得分:0)

只是澄清一点 - 他们没有“发明新语法”。

我不是100%确定最初的想法来自哪里,但使用“[]”表示列表,而“{}”表示Perl中存在的地图(其中那些用于构建数组引用和散列引用)

严格来说perl中没有“set”,但是set的最惯用的实现是map(map set member to 1),所以“{}”也适合。

所以Perl会说出与你列出的完全相同的东西:

$fruits = [ "Apple", "Mango", "Guava" ]; # Creates array reference
$flowers = { "Rose" => 1, "Daisy" => 1, "Chrysanthemum" => 1 };
     # or { map {$_=>1} ("Rose", "Daisy", "Chrysanthemum"))
$hindiNums = { 1 => "Ek", 2 => "Do", 3 => "Teen" }; 

我不是说上面的内容来自Perl,当然,它与至少一种其他语言一致,因此可能有更广泛的用途。

答案 8 :(得分:0)

这并不是全新的语法,因为Python,Javascript(json)和其他语言中都存在这样的文字。

我还没有看到有关Java 7的任何信息尚未坦白(最近专注于C ++和Javascript),但实际上很高兴看到这种语言的添加。

答案 9 :(得分:0)

你是对的,这只是空的句法糖。

此外,ArrayList.of(...)只是new ArrayList<...>(Arrays.asList(...))

的简写

答案 10 :(得分:0)

我认为其中一个原因是of( ... )会生成未经检查的警告,如果您尝试使用通用对象的实例填充它。

原因是...扩展为java数组,而java数组不喜欢泛型实例。

以下是处理此特定问题的规范中的示例:

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

目前无法以这种简洁的方式初始化此变量,并且没有未选中警告。