数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

一、函数式接口是什么? 所谓的函数式接口,实际上就是接口里面 只能有一个抽象方法的接口 。我们上一节用到的Comparator接口就是一个典型的函数式接口,它只有一个抽象方法compare。 只有一个抽象方法?那上图中的equals方法不是也没有函数体么?不急,和我一起往下看! 二、函数式接口的特点 接口有且仅有一个抽象方法,如上图的抽象方法compare 允许定义静态非抽象方法 允许定义默认defalut非抽象方法(default方法也是java8才有的,见下文) 允许java.lang.Object中的public方法,如上图的方法equals。 FunctionInterface注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错 甚至可以说:函数式接口是专门为lambda表达式准备的, lambda表达式是只实现接口中唯一的抽象方法的匿名实现类 。 三、default关键字 顺便讲一下default关键字,在java8之前 接口是不能有方法的实现,所有方法全都是抽象方法 实现接口就必须实现接口里面的所有方法 这就导致一个问题: 当一个接口有很多的实现类的时候,修改这个接口就变成了一个非常麻烦的事,需要修改这个接口的所有实现类 。 这个问题困扰了java工程师许久,不过在java8中这个问题得到了解决,没错就是default方法 default方法可以有自己的默认实现,即有方法体。 接口实现类可以不去实现default方法,并且可以使用default方法。 四、JDK中的函数式接口举例 java.lang.Runnable, java.util.Comparator, java.util.concurrent.Callable java.util.function包下的接口,如Consumer、Predicate、Supplier等 五、自定义Comparator排序 我们自定义一个排序器,实现compare函数(函数式接口Comparator唯一的抽象方法)。返回0表示元素相等,-1表示前一个元素小于后一个元素,1表示前一个元素大于后一个元素。这个规则和java 8之前没什么区别。 下面代码用自定义接口实现类的的方式实现:按照年龄的倒序排序! employees.sort(new Comparator() { [@Override](https://my.oschina.net/u/1162528) public int compare(Employee em1, Employee em2) { if(em1.getAge() == em2.getAge()){ return 0; } return em1.getAge() - em2.getAge() > 0 ? -1:1; } }); employees.forEach(System.out::println); 最终的打印结果如下,按照年龄的自定义规则进行排序。 Employee(id=8, age=79, gender=M, firstName=Alex, lastName=Gussin) Employee(id=7, age=68, gender=F, firstName=Melissa, lastName=Roy) Employee(id=10, age=45, gender=M, firstName=Naveen, lastName=Jain) Employee(id=3, age=43, gender=M, firstName=Ricky, lastName=Martin) Employee(id=4, age=26, gender=M, firstName=Jon, lastName=Lowman) Employee(id=1, age=23, gender=M, firstName=Rick, lastName=Beethovan) Employee(id=5, age=19, gender=F, firstName=Cristine, lastName=Maria) Employee(id=9, age=15, gender=F, firstName=Neetu, lastName=Singh) Employee(id=6, age=15, gender=M, firstName=David, lastName=Feezor) Employee(id=2, age=13, gender=F, firstName=Martina, lastName=Hengis) 这段代码如果以lambda表达式简写。箭头左侧是参数,右侧是函数体,参数类型和返回值根据上下文自动判断。如下: employees.sort((em1,em2) -> { if(em1.getAge() == em2.getAge()){ return 0; } return em1.getAge() - em2.getAge() > 0 ? -1:1; }); employees.forEach(System.out::println); 欢迎关注我的博客,里面有很多精品合集 本文转载注明出处(必须带连接,不能只转文字): 字母哥博客 。 觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。 《手摸手教你学Spring Boot2.0》 《Spring Security-JWT-OAuth2一本通》 《实战前后端分离RBAC权限管理系统》 《实战SpringCloud微服务从青铜到王者》 《VUE深入浅出系列》
来源:OSCHINA
发布时间:2020-06-29 08:26:00
作者:wt_better 链接: http://blog.csdn.net/wt_better/article/details/80992014 MyBatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。 以下是trim标签中涉及到的属性: 下面使用几个例子来说明trim标签的使用。 1、使用trim标签去除多余的and关键字 有这样的一个例子: 如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样: SELECT * FROM BLOG WHERE 这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样: SELECT * FROM BLOG WHERE AND title like ‘someTitle’ 你可以使用where标签来解决这个问题,where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。 trim标签也可以完成相同的功能,写法如下: state = #{state} AND title like #{title} AND author_name like #{author.name} 2、使用trim标签去除多余的逗号 有如下的例子: 如果红框里面的条件没有匹配上,sql语句会变成如下: INSERT INTO role(role_name,) VALUES(roleName,) 插入将会失败。 使用trim标签可以解决此问题,只需做少量的修改,如下所示: 其中最重要的属性是 suffixOverrides="," 表示去除sql语句结尾多余的逗号. 注:如果你有兴趣的话,也可以研究下Mybatis逆向工程生成的Mapper文件,其中也使用了trim标签,但结合了foreach、choose等标签,更多的是牵扯到Criterion的源码研究。不过研究完之后,你将熟练掌握mybatis各种标签的使用,学到Criterion的设计思想,对自己的启发将会很大。 微信搜索:【Java小咖秀】,更多精彩等着你,回复“手册”获取两份开心。
来源:OSCHINA
发布时间:2020-06-29 08:07:00
目录 上一篇 深入浅出Android NDK之崩溃分析 为了能在native层打印函数的调用堆栈,找了好久的资料,最后终于找到一个靠谱的链接: https://www.jianshu.com/p/4a5eeeee6d29 主要通过调用_Unwind_Backtrace函数来获得函数的调用堆栈,但是原文的并不好用,地址通过addr2line转换以后得不到函数名和行号,主要原因我们得到的地址是运行时地址,应该减去SO的基地址再来转换,下面看我改造后的例子,更好用。 #include #include #include #include #include static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg) { std::vector<_Unwind_Word> &stack = *(std::vector<_Unwind_Word>*)arg; stack.push_back(_Unwind_GetIP(context)); return _URC_NO_REASON; } void callstackDump(std::string &dump) { std::vector<_Unwind_Word> stack; _Unwind_Backtrace(unwindCallback, (void*)&stack); dump.append(" \n" "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n" "pid: 17980, tid: 17980, name: callstack.dump >>> callstack.dump <<<\n" "signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0\n" "r0 00000000 r1 00000000 r2 00000001 r3 00000001\n" "r4 e8efe008 r5 e0537b99 r6 ff970b88 r7 ff970a98\n" "r8 ff970de0 r9 e7904400 sl e790448c fp ff970b14\n" "ip e8ef985c sp ff970a60 lr e8eca00f pc e0537d86 cpsr 200b0030\n" "backtrace:\n"); char buff[256]; for (size_t i = 0; i < stack.size(); i++) { Dl_info info; if (!dladdr((void*)stack[i], &info)) { continue; } int addr = (char*)stack[i] - (char*)info.dli_fbase - 1; if (info.dli_sname == NULL || strlen(info.dli_sname) == 0) { sprintf(buff, "#%02x pc %08x %s\n", i, addr, info.dli_fname); } else { sprintf(buff, "#%02x pc %08x %s (%s+00)\n", i, addr, info.dli_fname, info.dli_sname); } dump.append(buff); } } void callstackLogcat(int prio, const char* tag) { std::string dump; callstackDump(dump); __android_log_print(prio, tag, "%s", dump.c_str()); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 把调用堆栈拼凑成崩溃日志的样子,主要是为了方便我们使用ndk-stack来解析。 下面来测试一下: void fun1() { callstackLogcat(ANDROID_LOG_DEBUG, "MD_DEBUG"); } void fun2() { fun1(); } void fun3() { fun2(); } extern "C" JNIEXPORT void Java_com_example_threadtest_PThread_start(JNIEnv *env, jclass clazz) { fun3(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 编译运行,得到以下输出: 2019-10-16 12:55:04.839 20856-20856/? D/MD_DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** pid: 17980, tid: 17980, name: callstack.dump >>> callstack.dump <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 r0 00000000 r1 00000000 r2 00000001 r3 00000001 r4 e8efe008 r5 e0537b99 r6 ff970b88 r7 ff970a98 r8 ff970de0 r9 e7904400 sl e790448c fp ff970b14 ip e8ef985c sp ff970a60 lr e8eca00f pc e0537d86 cpsr 200b0030 backtrace: #00 pc 00009fef /data/app/com.example.strtest-1/lib/arm/libstrtest.so #01 pc 0000a207 /data/app/com.example.strtest-1/lib/arm/libstrtest.so #02 pc 00009f91 /data/app/com.example.strtest-1/lib/arm/libstrtest.so #03 pc 00009f9f /data/app/com.example.strtest-1/lib/arm/libstrtest.so #04 pc 00009fa9 /data/app/com.example.strtest-1/lib/arm/libstrtest.so #05 pc 00009fc1 /data/app/com.example.strtest-1/lib/arm/libstrtest.so (Java_com_example_threadtest_PThread_start+00) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 通过ndk-stack转换一下,得到: C: