在本文中,我们将带你了解javalambda表达式中的双冒号的用法说明::在这篇文章中,我们将为您详细介绍javalambda表达式中的双冒号的用法说明::的方方面面,并解答javalambda两个冒
在本文中,我们将带你了解java lambda 表达式中的双冒号的用法说明 ::在这篇文章中,我们将为您详细介绍java lambda 表达式中的双冒号的用法说明 ::的方方面面,并解答java lambda 两个冒号常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的C# LINQ查询表达式及对应LAMBDA表达式的用法、c# – lambda表达式中的条件、C#中Lambda表达式的用法、C++ lambda表达式用法说明。
本文目录一览:- java lambda 表达式中的双冒号的用法说明 ::(java lambda 两个冒号)
- C# LINQ查询表达式及对应LAMBDA表达式的用法
- c# – lambda表达式中的条件
- C#中Lambda表达式的用法
- C++ lambda表达式用法说明
java lambda 表达式中的双冒号的用法说明 ::(java lambda 两个冒号)
这篇文章主要介绍了java lambda 表达式中的双冒号的用法说明 ::具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
双冒号运算就是Java中的[方法引用],[方法引用]的格式是
类名::方法名
注意是方法名哦,后面没有括号“()”哒。为啥不要括号,因为这样的是式子并不代表一定会调用这个方法。这种式子一般是用作Lambda表达式,Lambda有所谓懒加载嘛,不要括号就是说,看情况调用方法。
例如
表达式:
person -> person.getAge();
可以替换成
Person::getAge
表达式
() -> new HashMap();
可以替换成
HashMap::new
这种[方法引用]或者说[双冒号运算]对应的参数类型是Function T表示传入类型,R表示返回类型。比如表达式person -> person.getAge(); 传入参数是person,返回值是person.getAge(),那么方法引用Person::getAge就对应着Function类型。
下面这段代码,进行的操作是,把List里面的String全部大写并返还新的ArrayList,在前面的例子中我们是这么写的:
@Test public void converttest() { List collected = new ArrayList(); collected.add("alpha"); collected.add("beta"); collected = collected.stream().map(string -> string.toupperCase()).collect(Collectors.toList()); System.out.println(collected); }
现在也可以被替换成下面的写法:
@Test public void converttest() { List collected = new ArrayList(); collected.add("alpha"); collected.add("beta"); collected = collected.stream().map(String::toupperCase).collect(Collectors.toCollection(ArrayList::new));//注意发生的变化 System.out.println(collected); }
补充知识:Java解析属性配置文件并给占位符传参
我就废话不多说了,大家还是直接看代码吧~
//注册功能 public void register(User user){ //补齐数据 user.setUid(CommonUtils.uuid()); user.setStatus(false); user.setActivationCode(CommonUtils.uuid() + CommonUtils.uuid()); try { userDao.save(user); } catch (Exception e) { throw new RuntimeException(); } //发送邮件 //加载配置文件 Properties properties = new Properties(); try { properties.load(this.getClass().getClassLoader().getResourceAsstream("email_template.properties")); } catch (IOException e1) { throw new RuntimeException(); } String host = properties.getProperty("host"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); String from = properties.getProperty("from"); String to = user.getEmail(); String subject = properties.getProperty("subject"); //把占位符用后面的参数替换,后面参数可变 String content = messageformat.format(properties.getProperty("content"), user.getActivationCode()); //发送邮件3步曲 Session session = MailUtils.createSession(host, username, password); Mail mail = new Mail(from, to, subject, content); try { MailUtils.send(session, mail); } catch (Exception e) { throw new RuntimeException(); } }
以上这篇java lambda 表达式中的双冒号的用法说明 ::就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小编。
C# LINQ查询表达式及对应LAMBDA表达式的用法
C#编程语言非常优美,我个人还是非常赞同的。特别是在学习一段时间C#后发现确实在它的语法和美观度来说确实要比其它编程语言强一些(也可能是由于VS编译器的加持)用起来非常舒服,而且对于C#我觉得他最优美之处不仅仅是语法糖方面还有就是体现在LINQ和Lambda表达式。
本篇文简单介绍一下关于C#当中LINQ表达式和其对应的Lambda表达式的用法,关于这两部分内容的相关参考资料:
人民邮电出版社《C#程序设计及应用教程》(第3版)
博客:《c# Linq查询》
同时在介绍的时候我会尽量挑出重要部分同时加上我自己的理解和认识,如有偏差还请指教。
首先先让我们看一下什么是LINQ查询表达式和Lambda表达式:
运行结果:
以上是对LINQ查询表达式和Lambda表达式的一个简单的应用,都是查询stu列表中年龄大于等于20岁的结果并且把结果按照年龄降序排列。
由此可见Linq表达式和Lambda表达式并没有什么可比性,只是用Lambda可以实现LINQ的查询语句。
那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在《深入理解C#》中称其为“点标记”。
例子中主要以LINQ表达式为主,LINQ表达式结构更为清晰易于理解,同时也会给出对应的点标记写法(所有的LINQ查询表达式都可以转成对应的点标记。反之,不是所有的点标记都可以转成查询表达式。),所以如果想要了解这部分的读者也请往下看。本文会介绍LINQ查询表达式用法以及对应的Lambda表达式。
LINQ查询表达式是一组查询技术的统称,其主要思想是将各种查询功能直接集成到C#语言中,不论是对象、XML、还是数据库都可以用LINQ编写查询语句。LINQ与传统迭代技术实现的查询优势在于更简明、更易读这种优势特别是在筛选多个条件时更为显著;使用很少的程序代码便能实现复杂的查询和筛选;无需修改或者是进行很少的修改就能移植到其它的数据源。LINQ查询语句并不复杂并且与SQL语句有些类似,学习起来难度并不大。
接下来直接看LINQ查询例子:
//以下为例子中涉及查询的数据 List<Student> stu = new List<Student>() { new Student(){Id = 1,Name = "王同学",Age = 24}, new Student(){Id = 2,Name = "王同学",Age = 30}, new Student(){Id = 3,Name = "王同学",Age = 21}, new Student(){Id = 4,Name = "赵同学",Age = 20}, new Student(){Id = 5,Name = "钱同学",Age = 22}, new Student(){Id = 6,Name = "孙同学",Age = 23}, new Student(){Id = 7,Name = "周同学",Age = 23}, new Student(){Id = 8,Name = "吴同学",Age = 20}, new Student(){Id = 9,Name = "郑同学",Age = 25}, new Student(){Id = 10,Name = "蒋同学",Age = 26} };
查询年龄是30岁的王同学的信息:
//查询年龄是30岁的王同学的信息 var res = from t in stu where t.Name == "王同学" && t.Age == 30 select t; //对应的Lambda表达式 //var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同学"); foreach (var item in res)//显示查询结果 { Console.Write("学号:"+item.Id+"\n姓名:"+item.Name+"\n年龄:"+item.Age); }
运行结果:
LINQ查询表达式必须以form子句开头,并且必须以select或group子句结尾。在第一个from子句和最后一个select或group子句之间,查询表达式可以包含一个或者多个where、orderby、join、let甚至附加from子句。LINQ表达式整体的用法和SQL语句很像,在上面的例子中就可以看出。
上面的例子的含义就是从数据源stu中查询一个数据“t”,“t”满足的条件就是它的Name是王同学同时它的Age是30,然后查询这个“t”。LINQ查询语句的返回值类型为IEnumerable<T>,LINQ执行查询时,一般利用foreach循环执行查询得到一个序列,这这种方式称为“延迟执行”。
什么是“延迟执行”?还是上面例子中的查询:
//查询年龄是30岁的王同学的信息 var res = from t in stu where t.Name == "王同学" && t.Age == 30 select t; //var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同学");Lambda表达式写法 foreach (var item in res) { Console.Write("学号:"+item.Id+"\n姓名:"+item.Name+"\n年龄:"+item.Age); } Console.WriteLine("\n--------------------------------------------------------------------------"); stu.Add(new Student(){Id = 11,Name = "王同学",Age = 30}); foreach (var item in res) { Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age); Console.WriteLine(); }
运行结果:
延迟查询就是只需构造一次查询语句,可以多次使用。在List中添加新元素之后并没有重新执行查询操作,然而res中的结果却根据List中元素的改变相应发生了改变。
从学生中选出年龄小于25岁并且按照年龄降序排列
//从学生中选出年龄小于25岁并且按照年龄降序排列 var res = from t in stu where t.Age < 25 orderby t.Age descending select t; //var res1 = stu.Where(t => t.Age < 25).OrderByDescending(t => t.Age).Select(t => t);Lambda写法 foreach (var item in res) { Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age); Console.WriteLine(); }
运行结果:
从学生中查询姓王的同学的信息并且按照年龄降序排列
//从学生中查询姓王的同学的信息并且按照年龄降序排列 var res = from t in stu from n in t.Name where n == ''王''//名字中带有王字 orderby t.Age descending select t; //var res1 = stu.Where(t => t.Name.IndexOf("王") == 0).OrderByDescending(t => t.Age);lambda表达式 foreach (var item in res) { Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age); Console.WriteLine(); }
运行结果:
学生信息按照年龄、Id进行排序
//参数越靠前,优先级越高 //先按age排序,当分数相同时再按id排序...依次类推 var res = from t in stu orderby t.Age, t.Id select t; //var res1 = stu.OrderBy(t => t.Age).ThenBy(t => t.Id);Lambda表达式 foreach (var item in res) { Console.Write("学号:" + item.Id + "\n姓名:" + item.Name + "\n年龄:" + item.Age); Console.WriteLine(); }
运行结果:
按照年龄进行分组,查询相同年龄数量大于2的内容
//按照年龄进行分组,查询相同年龄数量大于2的内容 var res = from t in stu group t by t.Age into s where s.Count()>=2 select s; //var res1 = stu.GroupBy(t => t.Age).Where(s => s.Count() >= 2);lambda表达式 foreach (var item in res) { foreach (var items in item) { Console.Write("学号:" + items.Id + "\n姓名:" + items.Name + "\n年龄:" + items.Age); Console.WriteLine(); } Console.WriteLine(); }
运行结果:
查询出集合qSt中year等于集合qSc中year的元素并形成新的集合
List<s> pSt = new List<s>(); pSt.Add(new s() { year = 1999, name = "小张" }); pSt.Add(new s() { year = 2000, name = "小王" }); pSt.Add(new s() { year = 2001, name = "小李" }); pSt.Add(new s() { year = 2010, name = "小赵" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "aaa" }); pSc.Add(new school() { year = 2001, name = "bbb" }); pSc.Add(new school() { year = 2002, name = "ccc" }); pSc.Add(new school() { year = 2010, name = "ddd" }); pSc.Add(new school() { year = 2012, name = "fff" }); var res = from t1 in pSc from t2 in pSt where t1.year == t2.year select new {year = t1.year, name = t1.name + t2.name}; foreach (var item in res) { Console.Write("年:" + item.year + "姓名:" + item.name); Console.WriteLine(); }
运行结果:
并行linq
并行查询可以分解查询的工作,使其分布在多个线程上。当pc拥有多个cpu时,可以看到并行查询带来的改进效果。并行LINQ适用于大型的集合查询,并拥有一定的优势。使用System.Collections.Concurrent.Partitioner.Create可以手动创建分区器。可以粗鲁的认为并行linq对于大集合的查询是优势比较明显的。取消长时间运行的并行linq查询可以设置利用System.Threading.CancellationTokenSource设置取消操作。
Console.WriteLine("开始构造大数组..."); //构造大数组 const int count = 100000000; var data = new int[count]; var r = new Random(); for (int i = 0; i < count; i++) { data[i] = r.Next(40); } Console.WriteLine("开始计算..."); var st = System.DateTime.Now; var sum = (from x in data where x > 20 select x).Sum();//常规linq-耗时1.8641s var st2 = System.DateTime.Now; var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查询-耗时0.6620s //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询----x3 => x3 > 20(Lambda表达式) var st3 = System.DateTime.Now; /*Partitioner.Create 手动创建分区器以及终止LINQ查询的方法可以详见文初的博客链接 Create具有多个重载,可依据需求进行分区*/ var sum4 = (from c in System.Collections.Concurrent.Partitioner.Create(data, true).AsParallel() where c > 20 select c).Sum(); var dt1 = st2 - st; var dt2 = st3 - st2; Console.WriteLine("常规linq耗时:{0}s", dt1.TotalSeconds.ToString()); Console.WriteLine("并行linq耗时:{0}s", dt2.TotalSeconds.ToString()); Console.ReadKey();
运行结果:
写在最后,如果你对以上LINQ以及对应的Lambda的使用方法都已经了解那你已经初步了解了LINQ查询表达式和Lambda表达式,这里需要说明的一点是关于Lambda的使用方法并不仅仅只限于进行查询,他是一个主要用于简化委托的代码编写形式,他用法远比文中介绍的更加广泛,本文是为了对比展现LINQ和Lambda。
以上就是C# LINQ查询表达式及对应LAMBDA表达式的用法的详细内容,更多关于C# LINQ查询表达式及LAMBDA表达式的资料请关注其它相关文章!
- C#集合查询Linq在项目中使用详解
- C# Linq延迟查询的执行实例代码
- c# Linq查询详解
- c# 动态构建LINQ查询表达式
- C#使用LINQ查询表达式的基本子句总结
- C# linq查询之动态OrderBy用法实例
- C#中Linq延迟查询的例子
- C#使用linq语句查询数组中以特定字符开头元素的方法
- C#使用linq查询大数据集的方法
- C#中Linq查询基本操作使用实例
- C#使用LINQ查询操作符实例代码
c# – lambda表达式中的条件
< FOO>具有适当的orderType,第一个列表为0,第二个列表为1
在第一个列表中我进行过滤,我必须将第二个列表中的项添加到受分页限制的结果中.
基本上这是我的最终查询:
var listFoo= QueryList1.Concat(QueryList2); //(IQueriable) List<foo> listFoo =listFoo.OrderByDescending(r => r.ID) .ThenBy(d =>d.orderType) .Skip((currentPageIndex - 1) * pageSize) .Take(pageSize) .ToList();
这很有效,因为列表1作为主项目,列表2作为第一列表的详细信息.此外,我的过滤器应该只在第一个列表上工作.但问题来了.如何仅按日期订购第二个清单.我需要列出按日期排序的详细信息.
基本上我需要这样的东西:
List<foo> listFoo =listFoo.OrderByDescending(r => r.ID) .ThenBy(d =>d.orderType) .ThenBy(x=>(x.ordertype==1)?x.Date) .Skip((currentPageIndex - 1) * pageSize) .Take(pageSize) .ToList();
编辑:
List 1 : id =1,ordertype=0,Date = new DateTime(1950,1,4),[0] id =2,2,1) [1] List 2 : id =1,ordertype=1,5),[2] id =1,2),[3] id =1,3),[4] id =1,4) [5] This should be ordered as follows : [0],[3],[4],[5],[2],[1]
解决方法
listFoo = listFoo.OrderByDescending(r => r.ID) .ThenBy(d =>d.orderType) .ThenBy(x => (x.ordertype==1) ? x.Date : DateTime.MinValue) .Skip((currentPageIndex - 1) * pageSize) .Take(pageSize) .ToList();
如果你不关心订单,如果ordertype不是1,那么else条件是任意的.
C#中Lambda表达式的用法
从C#3.0开始,可以使用lambda表达式把实现代码赋予委托。lambda表达式与委托(https://www.jb51.net/article/244051.htm)直接相关。当参数是委托类型时,就可以使用lambda表达式实现委托引用。
static void Main() { string mid = ", middle part,"; Func<string, string> anonDel = param => { param += mid; param += " and this was added to the string."; return param; }; Console.WriteLine(anonDel("Start of string")); }
lambda运算符“=>” 的左边是参数列表,右边是lambda变量的方法的实现代码。
1.参数
如果lambda表达式只有一个参数,只写出参数名就可以,像上面的代码。
如果委托使用多个参数,就需要把参数名放到括号中:
Func<double, double, double> twoParams = (x, y) => x * y; Console.WriteLine(twoParams(3, 2));
可以在括号中给变量名添加参数类型:
Func<double, double, double> twoParamsWithTypes = (double x, double y) => x * y; Console.WriteLine(twoParamsWithTypes(4, 2));
2.多行代码
如果lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐形的return语句。
Func<double, double, double> twoParams = (x, y) => x * y; Func<double, double, double> twoParams = (x, y) => { retrun x * y; }
如果在lambda表达式的实现代码中有多条语句,就必须添加花括号和return语句:
Func<string, string> anonDel = param => { param += mid; param += " and this was added to the string."; return param; };
3.闭包
通过lambda表达式可以访问lambda表达式块外部的变量,这称为闭包。闭包是一个很好的功能,但如果使用不当,会很危险。例如:
int someVal = 5; Func<int,int> f = x => x+someVal;
假定以后修改了变量someVal,于是调用委托f时,会使用someVa的新值:
someVal = 7; f(3);//结果为10而不是8.
特别是,通过另一个线程调用lambda表达式时,我们可能不知道进行了这个调用,也不知道外部变量的当前值是什么。
所以在使用闭包时,一定要谨慎!!!
在lambda表达式访问lambda表达式块外部的变量时,编译器在定义lambda表达式时,编译器会创建一个匿名类,它用一个构造函数来传递外部变量。该构造函数取决于从外部传递进来的变量个数和类型。
对于lambda表达式Func<int,int> f = x => x+someVal;
public class AnonymousClass { private int someVal; public AnonymousClass(int someVal) { this.someVal = someVal; } public int AnonymousMethod(int x) { retrun x+someVal; } }
使用lambda表达式并调用该方法的时,会创建匿名类的一个实例,并传递调用该方法时变量的值。
4.使用foreach语句的闭包
先看下面这个例子:
var values = new List<int>() {10,20,30}; var funcs = new List<Func<int>>(); foreach(var val in values) { funcs.Add(() => val); } foreach(var f in funcs) { Console.WriteLine((f())); }
第一条foreach语句添加了funcs列表中每个元素。添加到列表中的函数使用lambda表达式。该lambda表达式使用了一个变量val,该变量在lambda表达式的外部定义为foreach语句的循环变量。第二条foreach语句迭代funcs列表,以调用列表中引用的每个函数。
在C#5.0之前版本编译这段代码时,会在控制台输出30三次。这是因为,在第一个foreach循环中使用闭包,所创建的函数是在调用时,而不是在迭代时获得val变量的值。在https://www.jb51.net/article/244045.htm中介绍foreach时讲到编译器会从foreach语句中创建一个while循环。在C#5.0之前版本中,编译器在while循环外部定义循环变量,在每次迭代中重用这个变量。因此,在循环结束时,该变量的值就是最后一次迭代时的值。要想在使用C#5.0之前版本时,输出10,20,30,需要将代码改为使用一个局部变量:
var values = new List<int>() {10,20,30}; var funcs = new List<Func<int>>(); foreach(var val in values) { var v = val; funcs.Add(() => v); } foreach(var f in funcs) { Console.WriteLine((f())); }
在C#5.0中,不再需要做这种代码修改。C#5.0会在while循环的代码中创建一个不同的局部循环变量。
到此这篇关于C#中Lambda表达式的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。
- C#中Lambda表达式的用法
- C#中Lambda表达式的三种写法
- C# 内部类与Lambda表达式用法详解
- C# lambda表达式原理定义及实例详解
- 理解C#中的Lambda表达式
- 初步认识C#中的Lambda表达式和匿名方法
- C#特性之匿名方法和Lambda表达式
- C#实现递归调用的Lambda表达式
C++ lambda表达式用法说明
C++ lambda表达式的本质就是重载了 operator(),lambda是一个类,在调用时会进行编译展开。因此lambda表达式对象其实就是一个匿名的functor,所以 lambda 表达式 也叫匿名函数对象。
C++中lambda表达式的构成
一个标准的lambda表达式包括:捕获列表、参数列表、mutable指示符、异常列表、返回类型(->返回类型)和函数体:
[捕获列表] (形参列表) mutable 异常列表-> 返回类型
{
函数体
}
各项的含义:
-
捕获列表:捕获外部变量,捕获的变量可以在函数体中使用,可以省略,即不捕获外部变量。
-
形参列表:和普通函数的形参列表一样。可省略,即无参数列表
-
mutable:mutable 关键字,如果有,则表示在函数体中可以修改捕获变量,根据具体需求决定是否需要省略。
-
异常列表:noexcept / throw(...),和普通函数的异常列表一样,可省略,即代表可能抛出任何类型的异常。
-
返回类型:和函数的返回类型一样。可省略,如省略,编译器将自动推导返回类型。
-
函数体:代码实现。可省略,但是没意义。
捕获列表
由于lambda表达式是在某函数内定义的,因此我们可能希望其能使用函数内的局部变量,这时则可以使用所谓捕获列表。总体说来,一共有三种捕获方式:值捕获、引用捕获和外部捕获。
值捕获
值捕获和参数传递中的值传递类似,被捕获的变量的值在Lambda表达式创建时通过值拷贝的方式传入,因此随后对该变量的修改不会影响影响Lambda表达式中的值。注意,不能在lambda表达式中修改捕获变量的值。代码如下:
#include <iostream>
using namespace std;
int main()
{
int nCapture = 13;
auto f = [nCapture](int a, int b) -> int
{
//nCapture = 134; //不能在lambda表达式中修改捕获变量的值
return a + b + nCapture;
};
cout << f(4, 3) << endl;
cout << "nCapture=" << nCapture << endl;
return 0;
}
引用捕获
使用引用捕获一个外部变量,需在捕获列表变量前面加上一个引用说明符&。如下:
#include <iostream>
using namespace std;
int main()
{
int nCapture = 13;
auto f = [&nCapture](int a, int b) -> int
{
cout << "In functor before change nCapture=" << nCapture << endl; //在调用lamd之前 nCapture = 12345
nCapture = 134;
cout << "In functor after change nCapture=" << nCapture << endl; // nCapture = 134
return a + b + nCapture;
};
nCapture = 12345;
cout << f(4, 3) << endl;
cout << "nCapture=" << nCapture << endl; //经过了lambda计算后,nCapture值变为修改后的134
return 0;
}
代码结果:
In functor before change nCapture=12345
In functor after change nCapture=134
141
nCapture=134
根据以上说明,引用捕获,可以在lambda函数体修改捕获的值。
隐式捕获
上面的值捕获和引用捕获都需要我们在捕获列表中显示列出Lambda表达式中使用的外部变量。除此之外,我们还可以让编译器根据函数体中的代码来推断需要捕获哪些变量,这种方式称之为隐式捕获。隐式捕获有两种方式,分别是[=]和[&]。[=]表示以值捕获的方式捕获外部变量,[&]表示以引用捕获的方式捕获外部变量。
lambda表达式的应用场景:
(1)Qt信号槽,槽函数可以用lambda表达式来写;
(2)线程代码
- 点赞
- 收藏
- 分享
-
- 文章举报

今天关于java lambda 表达式中的双冒号的用法说明 ::和java lambda 两个冒号的介绍到此结束,谢谢您的阅读,有关C# LINQ查询表达式及对应LAMBDA表达式的用法、c# – lambda表达式中的条件、C#中Lambda表达式的用法、C++ lambda表达式用法说明等更多相关知识的信息可以在本站进行查询。
本文标签: