Lambda(->) 转换为双冒号(::) 方法引用

huangapple go评论72阅读模式
英文:

Lambda(->) to Double colon(::) method reference

问题

在这里,我尝试使用lambda表达式打印值。是否可以用双冒号的方式来做呢?

setVals.stream().forEach(s -> System.out.println(s + " : " + Collections.frequency(listColors, s)));

是否有可能使用双冒号?

方法引用和按引用传递是相同的吗?

我可以看到双冒号是传递方法引用的方式。
但在这个Slack答案中,我可以看到在Java中没有按引用传递的概念。
https://stackoverflow.com/a/73021/11962586

英文:

here I'm trying to print values using lambda. Is it possible to make it in double colon way?

public class Occurance 
{
	static void occuranceUsingListSet()
	{
		ArrayList<String> listColors = new ArrayList<>(Arrays.asList("Red","blue","green","green"));
		Set<String> setVals = new LinkedHashSet<>(listColors);
		setVals.stream().forEach(s -> System.out.println(s + " : " + Collections.frequency(listColors, s)));
	}
	
}

setVals.stream().forEach(s -> System.out.println(s + " : " + Collections.frequency(listColors, s)));

Is there any possibilities to use double colon?

And is method reference and pass by reference are same?

I can see this double colon is pass method reference.
But in this slack answer I can see that there is no such thing like pass by reference in java.
https://stackoverflow.com/a/73021/11962586.

答案1

得分: 4

不可以用单个方法引用完成整个操作。在你的lambda表达式中,你执行的不止是一个方法调用。

不过,如果你将字符串创建重构为一个新的函数,那么你可以使用方法引用来调用 System.out.println

static void occuranceUsingListSet() {
    // 你不需要将 Arrays.asList 包装在一个新的 ArrayList 中。
    List<String> listColors = Arrays.asList("Red", "blue", "green", "green");
    Set<String> setVals = new LinkedHashSet<>(listColors);

    setVals.stream()
        .map(s -> createFrequencyString(s, listColors))
        .forEach(System.out::println);
}

static String createFrequencyString(String color, List<String> colors) {
    return color + " : " + Collections.frequency(colors, color);
}
英文:

No, you cannot do that whole operation with a single method reference. You are doing more than a single method call in your lambda.

Although, if you refactor your string creation into a new function, then you can use a method reference to call System.out.println:

static void occuranceUsingListSet() {
    // You don&#39;t need to wrap Arrays.asList in a new ArrayList.
    List&lt;String&gt; listColors = Arrays.asList(&quot;Red&quot;,&quot;blue&quot;,&quot;green&quot;,&quot;green&quot;);
    Set&lt;String&gt; setVals = new LinkedHashSet&lt;&gt;(listColors);

    setVals.stream()
        .map(s -&gt; createFrequencyString(s, listColors);
        .forEach(System.out::println);
}

static String createFrequencyString(String color, List&lt;String&gt; colors) {
    return color + &quot; : &quot; + Collections.frequency(colors, color);
}

答案2

得分: 1

以下是您要求的中文翻译部分:

"With a little reworking of the method you can use a method reference. Since you didn't specify if a set was required, I am using a map as it offers some efficiencies."
"通过稍微修改方法,您可以使用方法引用。由于您没有指定是否需要一个set,我正在使用一个map,因为它提供了一些效率。"

List<String> listColors = Arrays.asList("Red", "blue", "green", "green");
List<String> listColors = Arrays.asList("Red", "blue", "green", "green");

"I am calling the method printOccurrences since that is what you are doing. It takes a Supplier<Stream<String>> as the parameter. The stream is obtained in the method by using get()."
"我称这个方法为printOccurrences,因为这就是您正在做的事情。它以Supplier<Stream<String>>作为参数。在方法内部,使用get()获取流。"

printOccurrences(listColors::stream);
printOccurrences(listColors::stream);

"prints"
"打印输出"

Red : 1, blue : 1, green : 2
Red : 1, blue : 1, green : 2

"Using Collections.frequency is ill advised since you must traverse the entire list for each specified object. Using a Map to compute frequencies is a more common technique as it does it in a single pass over the list. For each color string, Collectors.groupingBy along with Collectors.counting will compute the frequency for each map entry pair of <String, Long>. The entries are then streamed to obtain the collected data and joined into a string for printing (the format of which can be altered as required). I used a LinkedHashMap supplier to preserve the order of colors as they are processed. If not required or desired, it can be removed."
"使用Collections.frequency不是一个明智的选择,因为您必须为每个指定的对象遍历整个列表。使用Map来计算频率是一种更常见的技术,因为它在列表上只执行一次遍历。对于每个颜色字符串,Collectors.groupingByCollectors.counting将计算<String, Long>映射条目对的频率。然后,对这些条目进行流式处理以获取收集的数据,并将其连接到一个字符串中以供打印(可以根据需要更改格式)。我使用了LinkedHashMap的供应商以保留颜色的处理顺序。如果不需要或不希望保留顺序,可以将其删除。"

"So in order

  • get the stream and compute the frequencies using groupingBy
  • then stream the entry set, extracting the key(color String) and value(frequency) and format for joining. I am joining each pair with , .
  • all of the above is then passed to System.out.println."
    "所以按顺序
  • 获取流并使用groupingBy计算频率
  • 然后流式处理条目集,提取键(颜色字符串)和值(频率)并格式化连接。我用, 连接每一对。
  • 所有以上内容然后传递给System.out.println。"
static void printOccurrences(Supplier<Stream<String>> stream) {
     System.out.println(stream.get()
             .collect(Collectors.groupingBy(color -> color,
                     LinkedHashMap::new, Collectors.counting()))
             .entrySet().stream().map(e -> e.getKey() + " : " + e.getValue())
             .collect(Collectors.joining(", ")));
}
static void printOccurrences(Supplier<Stream<String>> stream) {
     System.out.println(stream.get()
             .collect(Collectors.groupingBy(color -> color,
                     LinkedHashMap::new, Collectors.counting()))
             .entrySet().stream().map(e -> e.getKey() + " : " + e.getValue())
             .collect(Collectors.joining(", ")));
}

"Some final notes.

  • The method above can also be easily altered to return the string for printing and/or take the list as an argument and just stream it there without using a Supplier.

  • Unless you want &quot;Red&quot; to be different than &quot;red&quot; you should convert to a common case, otherwise they will be treated as different colors. For something like this, title case might be a nice choice so it can be done as follows:"
    "一些最后的注意事项。

  • 上面的方法也可以轻松修改为返回打印用的字符串,和/或将列表作为参数,并在那里流式处理,而不使用供应商。

  • 除非您希望&quot;Red&quot;&quot;red&quot;不同,否则您应该将它们转换为通用大小写,否则它们将被视为不同的颜色。对于这样的情况,标题大小写可能是一个不错的选择,可以按照以下方式进行转换:"

static String toTitleCase(String str) {
     return str.substring(0,1).toUpperCase() + str.substring(1).toLowerCase();
}
static String toTitleCase(String str) {
     return str.substring(0,1).toUpperCase() + str.substring(1).toLowerCase();
}

"Then change a -> a in groupingBy to a->toTitleCase(a)"
"然后在groupingBy中将a -> a更改为`a

英文:

With a little reworking of the method you can use a method reference. Since you didn't specify if a set was required, I am using a map as it offers some efficiencies.

List&lt;String&gt; listColors = Arrays.asList(&quot;Red&quot;, &quot;blue&quot;, &quot;green&quot;,
        &quot;green&quot;);

I am calling the method printOccurrences since that is what you are doing. It takes a Supplier&lt;Stream&lt;String&gt;&gt; as the parameter. The stream is obtained in the method by using get().

printOccurrences(listColors::stream);

prints

Red : 1, blue : 1, green : 2

Using Collections.frequency is ill advised since you must traverse the entire list for each specified object. Using a Map to compute frequencies is a more common technique as it does it in a single pass over the list. For each color string, Collectors.groupingBy along with Collectors.counting will compute the frequency for each map entry pair of &lt;String, Long&gt;. The entries are then streamed to obtain the collected data and joinedinto a string for printing (the format of which can be altered as required). I used a LinkedHashMap supplier to preserve the order of colors as they are processed. If not required or desired, it can be removed.

So in order

  • get the stream and compute the frequencies using groupingBy
  • then stream the entry set, extracting the key(color String) and value(frequency) and format for joining. I am joining each pair with &quot;, &quot;.
  • all of the above is then passed to System.out.println.
static void printOccurrences(Supplier&lt;Stream&lt;String&gt;&gt; stream) {
     System.out.println(stream.get()
             .collect(Collectors.groupingBy(color -&gt; color,
                     LinkedHashMap::new, Collectors.counting()))
             .entrySet().stream().map(e -&gt; e.getKey() + &quot; : &quot; + e.getValue())
             .collect(Collectors.joining(&quot;, &quot;)));
}

Some final notes.

  • The method above can also be easily altered to return the string for printing and/or take the list as an argument and just stream it there without using a Supplier.

  • Unless you want &quot;Red&quot; to be different than &quot;red&quot; you should convert to a common case, otherwise they will be treated as different colors. For something like this, title case might be a nice choice so it can be done as follows:

static String toTitleCase(String str) {
     return str.substring(0,1).toUpperCase() + str.substring(1).toLowerCase();
}

Then change a -&gt; a in groupingBy to a-&gt;toTitleCase(a)



</details>



huangapple
  • 本文由 发表于 2023年6月25日 23:24:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76551128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定