英文:
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't need to wrap Arrays.asList in a new 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);
}
答案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.groupingBy与Collectors.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
"Red"
to be different than"red"
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:"
"一些最后的注意事项。 -
上面的方法也可以轻松修改为返回打印用的字符串,和/或将列表作为参数,并在那里流式处理,而不使用供应商。
-
除非您希望
"Red"
与"red"
不同,否则您应该将它们转换为通用大小写,否则它们将被视为不同的颜色。对于这样的情况,标题大小写可能是一个不错的选择,可以按照以下方式进行转换:"
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<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(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 <String, Long>
. 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
", "
. - all of the above is then passed to
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(", ")));
}
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
"Red"
to be different than"red"
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 -> a
in groupingBy
to a->toTitleCase(a)
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论