28

从有关 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 开发人员 Brian Goetz 的电子邮件,总结了不包括此功能的理由;这是提案本身.)

4

11 回答 11

11

回答问题 2:

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

给你一个不可变的列表。

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

在此处阅读详细信息:提案:集合文字

对问题 1 的回答:是的。这是风格问题。

于 2010-04-23T18:36:08.590 回答
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();
于 2010-04-23T18:05:26.543 回答
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"] } 
    };

我在十二行非常清晰的行中打包了大量数据。如果我使用ArrayList.of(十次)和一些类似的地图构造函数(四次,使用十个 Map.EntryPair!),函数调用会使代码变得臃肿并使其更难阅读。

虽然它绝对属于语法糖领域,但这是我在 Java 7 中期待的第一大特性(如果它出来的话)。

于 2011-03-31T15:20:52.307 回答
3

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

是... mmhh 太冗长了,他们决定添加这个解决方案。

另一个增强功能是数字文字,因此您将能够键入:

 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;
                     }};
                 }};
             };
         }};
     }};
 }};
于 2010-04-23T18:41:37.063 回答
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
                    }
                }
            ]
        }
    }
}

我认为这种编程风格当然适用于某些应用领域。到头来还是口味问题。。。

于 2010-04-23T18:11:51.377 回答
1

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

于 2010-04-23T17:57:59.367 回答
1

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;

这会给我们的生活增添新的东西吗?嗯,不。它会让我们的生活更轻松吗?我想是的。

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

于 2010-04-23T18:17:49.233 回答
0

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

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

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

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

目前没有办法以这种简洁的方式初始化这个变量并且没有未经检查的警告。

于 2010-04-23T18:36:59.270 回答
0

Just to clarify one point - they did not "invent new syntax".

I'm not 100% sure where the original idea came from, but using "[]" to denote lists and "{}" to denote maps exists in Perl (where those are used in building array refs and hash refs).

There's no "set" in perl strictly speaking but the most idiomatic implementation of a set is a map (map set member to 1), so "{}" also fits.

So Perl would say exactly the same things as you listed as:

$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" }; 

I'm not saying the above came from Perl, of course, but it is consistent with at least one other language and thus possibly with a wider use.

于 2010-04-23T17:55:20.853 回答
0

它不是全新的语法,因为 Python、Javascript (json) 和可能的其他语言中都存在这种文字。

坦率地说,我还没有看到任何关于 java 7 的信息(最近专注于 C++ 和 Javascript),但看到这样的语言添加实际上是件好事。

于 2010-04-23T17:59:39.147 回答
0

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

ArrayList.of(...)也只是简写new ArrayList<...>(Arrays.asList(...))

于 2010-04-23T18:22:14.687 回答