为什么要集合文字?

发布于 2024-08-30 05:21:34 字数 1041 浏览 10 评论 0原文

从有关 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. 是否可以提供静态方法<所有集合类中的 code>of 可以按如下方式使用:

List; Fruits = ArrayList.of("Apple", "Mango", "Guava");

在我看来,这看起来和字面版本一样好,而且也相当简洁。那么为什么他们必须发明一种新语法(编辑:“新”我的意思是“Java 的新语法”。)?

  1. 当我说 List时Fruits = [ "Apple", "Mango", "Guava" ]; 我实际上会得到什么List?它会是 ArrayList 或 LinkedList 还是其他东西?

1 正如评论中所指出的,集合文字没有符合 Java 7,也没有符合 Java 8。(这是一个 来自 Oracle 开发人员 Brian Goetz 的电子邮件,总结了不包含此功能的理由;以及这是提案本身。)

From the various online articles on Java 7 I have come to know that Java 7 will be having collection literals1 like the following:

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

My questions are:

  1. Wouldn't it have been possible to provide a static method of in all of the collection classes which could be used as follows:

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

IMO this looks as good as the literal version and is also reasonably concise. Why then did they have to invent a new syntax (EDIT: By 'new' I mean 'new to Java'.)?

  1. When I say List<String> fruits = [ "Apple", "Mango", "Guava" ]; what List would I actually get? Would it be ArrayList or LinkedList or something else?

1 As noted in the comments, collection literals did not make the cut for Java 7, nor indeed Java 8. (Here's an email from Brian Goetz, an Oracle developer, summarizing the rationale for not including this feature; and here is the proposal itself.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

负佳期 2024-09-06 05:21:35

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

Language design is a matter of taste. Having said that, this kind of list/object initialization has become very popular. For example, C# has almost the same thing. The syntax is quite flexible and, as even your examples show, lets you initialize something like a dictionary inline. I rather like the syntax the designers chose here.

听闻余生 2024-09-06 05:21:35

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;

:这会给我们的生活带来真正新的东西吗?嗯,不。它会让我们的生活变得更轻松吗?我想,是的。

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

IMO this is just a Syntactic sugar that simplifies code a bit. Why are you not surprised by a sugar of the same kind:

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

It is just a convenient way to express a simple idea instead of writing something like

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

Does this add something really new to our life? Well, no. Does it makes our lives a bit easier? I think, yes.

Regarding second part of question, I don't know what actual types would be. But frankly speaking, how often do you care what collection implementation is? Especially taking into account that such collections are expected to be relatively small (with all values typed by a developer). Anyway, in those rare cases when you do care, just don't use this simplified syntax and do the job yourself.

夏日落 2024-09-06 05:21:35

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

坦白说,我还没有看到任何关于 java 7 的信息(最近主要关注 C++ 和 Javascript),但看到这种语言的这样一个补充实际上是很好的。

It's not entirely new syntax as such literals are present in Python, Javascript (json) and probably other languages.

I haven't seen any information on java 7 yet to be frank (were focused on C++ and Javascript lately), but it's actually good to see such an addition to the language.

残龙傲雪 2024-09-06 05:21:35

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

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

严格来说,perl 中没有“集合”,但集合最惯用的实现是映射(将集合成员映射为 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,但它与至少一种其他语言一致,因此可能具有更广泛的用途。

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.

清晰传感 2024-09-06 05:21:35

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

另外,您的 ArrayList.of(...) 只是 new ArrayList<...>(Arrays.asList(...)) 的简写

You are right this is just empty syntactic sugar.

Also your ArrayList.of(...) would be just short hand for new ArrayList<...>(Arrays.asList(...))

看春风乍起 2024-09-06 05:21:35

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

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

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

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

目前无法以这种简洁的方式初始化此变量,并且不会出现未检查警告。

I think one of the reasons, is that of( ... ) will generate an unchecked warning if you would try to populate it with instances of generic objects.

The reason, ... expands to a java array, and java arrays do not like generic instances.

Here is an example from the spec that deals with this specific issue:

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

There is currently no way to initialize this variable in this concise manner and without unchecked warning.

昵称有卵用 2024-09-06 05:21:34

问题 2 的答案:

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

为您提供一个不可变列表。

该提案的整体思想是子类型不能被指定。编译器根据右侧的集合选择合适的实现。

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

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

Answer to question 2:

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

gives you an immutable list.

The whole idea of this proposal that the subtype cannot be specified. The compiler chooses a suitable implementation depending on the collection on the right-hand side.

Read the details here: Proposal: Collection Literals

Answer to question 1: yes it would have. It's a matter of style.

憧憬巴黎街头的黎明 2024-09-06 05:21:34

另一件需要注意的事情是,对于列表来说,使用 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();

Another thing to note is that for lists this is very easy using var args, but have a little think about how you'd do it for a map. There is no way to supply pairs of arguments to a var args method, unless you introduce an extra Map.Entry object or something like that.

So using existing syntax you'd end up with

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

which would get very tiring very quickly.

Even if you go down the path of using a builder pattern (as we do) then it's pretty ugly

Map<String,String> map = CollectionUtil.<String,String>map()
                                        .put( "key1", "value1" )
                                        .put( "key2", "value2" )
                                        .map();
三生殊途 2024-09-06 05:21:34

上面没有提到的是集合的集合的简单性。假设您想要一个常量来存储不同国家的货币名称和价值。

// 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 中期待的 #1 功能(如果它出现的话)。

Not mentioned above is the simplicity of collections of collections. Lets say you want a constant to store the currency names and values of different countries.

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

I have pack an enormous amount of data in twelve extremely legible lines. Had I used ArrayList.of (ten times) and some similar map constructor (four times, with ten Map.EntryPair!), the function calls would have bloated the code and made it significantly harder to read.

While it is definitely in the domain of syntactic sugar, this is the #1 feature I'm looking forward to in Java 7 (if it ever gets out).

孤独难免 2024-09-06 05:21:34

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

A1 Yes it is possible, but requires you to type more and more.

While this is not certainly something essentially wrong, it is one of the things developer complain more about. They ( and sometimes I do my self ) feel that Java is too verbose.

As the hardware got faster, new programming languages which at the beginning were too expensive to perform computations became feasible, and they are now being used more and more and are very popular. When developers have to type in Java again they feel, like oh no:, public static void main again! kind of.

One of the things that Java ( and statically types languages in general ) had to increase execution speed is to perform as many validations as possible before running ( that is, in the compiling stage )

These new programming languages ( remarkably Python and Ruby ) make a joy to program in, because you have to type less to achieve the same.

The reaction Java is taking to this, is to make the language bigger and incorporate some of this "syntactic sugar" into the language, that's why.

Even programming languages like C# had these extended features ( properties comes to my mind ) to make the developer code less.

At the end, I think these additions benefit the language, but they have to be added very carefully, to avoid break the compatibility and/or create a language that is so big, that nobody can use it.

I think an alternative would've been to allow the methods to be more expressive in their names, but that's very complicated, for Java. Perhaps in a new language :).

The Map put method signature could have been like this:

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

That's allow the method name be: [(key)]=(value) and eventually omit the parenthesis ( like in Ruby or originally in Smalltalk ) so this method would be:

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

Since that's not possible ( because []= are not valid method identifiers ) and writing:

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

Is ... mmhh too verbose, they decided to add this solution.

Another enhancement are number literals, so you will be able to type:

 int million = 1_000_000;

A2 : You will get something else.

A3 ( expanding my comment on kloffy answer ).

You could write that same code in Java as of today.

Granted Stage, Scente, Group, Text, ImageView, Image were existing Java classes, you could type:

 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;
                     }};
                 }};
             };
         }};
     }};
 }};
云醉月微眠 2024-09-06 05:21:34

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

我认为这种编程风格肯定适合某些应用程序领域。归根结底,这始终是一个品味问题......

They might have been inspired by the declarative programming style of JavaFX. If that is the case however, I'm disappointed that they didn't go all the way to support object literals as well. Here's an example of object literals in 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
                    }
                }
            ]
        }
    }
}

I think that this style of programming certainly lends itself to certain application areas. In the end it's always a matter of taste...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文