首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Golang学习笔记之方法(method)

法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver)。• 只能为当前包内命名类型定义⽅法。• 参数 receiver 可任意命名。如⽅法中未曾使⽤,可省略参数名。• 参数 receiver 类型可以是 T 或 *T。基类型 T 不能是接⼝或指针。• 不⽀持⽅法重载, receiver 只是参数签名的组成部分。• 可⽤实例 value 或 pointer 调⽤全部⽅法,编译器⾃动转换。• Go 不允许同名函数,但是同名方法可以定义在不同的类型上• method和receiver必须在同一个包里定义• 作为函数参数,值类型就是值类型,指针类型就是指针类型• 方法有一个值类型和指针类型的接受者时,都可以直接调用,内部会自动进行语法的转换。 一个方法只是一个函数,它有一个特殊的接收者(receiver)类型,该接收者放在 fu

优秀的个人博客,低调大师

Spring Boot 教程系列学习

Spring Boot基础教程1-Spring Tool Suite工具的安装 Spring Boot基础教程2-RESTful API简单项目的快速搭建 Spring Boot基础教程3-配置文件详解:Properties和YAML Spring Boot基础教程4-配置文件-多环境配置 Spring Boot基础教程5-日志配置-logback和log4j2 Spring Boot基础教程6-web应用开发-模板引擎FreeMarker Spring Boot基础教程7-web应用开发-模板引擎Thymeleaf Spring Boot基础教程8-web应用开发-模板引擎jsp Spring Boot基础教程9-web应用开发-错误处理 Spring Boot基础教程10-web应用开发-Servlets, Filters, listeners Spring Boot基础教程11-web应用开发-CORS支持 Spring Boot基础教程12-web应用开发-文件上传 点击链接加入群聊【Spring Boot Cloud技术交流】:https://jq.qq.com/?_wv=1027&k=5FDiKZw 插件篇 Elicpse使用技巧-打开选中文件文件夹或者包的当前目录 (更详细的讲解请观看视频,源码也在相应的文档里面) 视频教程:http://www.roncoo.com/course/view/c99516ea604d4053908c1768d6deee3d 源码地址:https://github.com/roncoo/spring-boot-demo 1.工具下载地址: Eclipse:http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/neonr Spring Tool Suite:https://spring.io/tools/sts/all 2.使用版本为: Eclipse:eclipse-jee-neon-R-win32-x86_64.zip Spring Tool Suite:springsource-tool-suite-3.8.0.RELEASE-e4.5.2-updatesite.zip 3.安装步骤: 3.1 解压Eclipse,打开Help ---> Install New Sofware... 3.2 点击右上角位置的:Add... 3.3 点击右上角位置的:Loccal...,选中解压之后的springsource-tool-suite-3.8.0.RELEASE-e4.5.2-updatesite,,之后点击 OK 3.4 点击 Select All,之后确认,后面有多次需要确认,会花费一定的时间,请耐心等待,安装完成之后,会提示重启。 小提示:可以选中在线安装Spring Tool Suite 这个插件。Help ---> Eclipse Marketplce...之后搜索spring tool suite 注意版本的选择 查看Eclipse版本:Help ---> About Eclipse

优秀的个人博客,低调大师

c++命名空间 namespace学习

我们为什么需要命名空间? 我们假设一下这种情况,在A班中,有一名同学叫小明,在B班中,也有一名同学叫小明,现在两个班的同学一起聚会,老师找A班的小明,这时候他在人群中喊一声小明肯定两个小明都过来了,这个时候B班小明就白跑一趟了,为了避免这种尴尬,老师只要喊“A班的小明过来一下就行了”。在c++已经其他某些语言中,也是这个道理,在很多大型项目中,由于可能多人一起开发,难免出现相同名字的变量,这个时候我们就需要namespace了,在调用同名变量时,另外加上它的namespace,这样就避免了出错。 1.命名空间实例 //namespace study #include<iostream> using namespace std; namespace first_space{ void func(){ cout<<"my first_space"<<endl; } } namespace second_space{ void func(){ cout<<"my second_space"<<endl; } } int main(){ first_space::func(); second_space::func(); } 2.using指令 您可以使用using namespace指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。 //namespace study #include<iostream> using namespace std; namespace using_space{ void beusing(){ cout<<"I am using"<<endl; } } using namespace using_space; //namespace using_space{ // void beusing(){ // cout<<"I am using"<<endl; // } //} int main(){ beusing(); } 这里注意using namespace必须在被调用空间定义后再使用。 using 指令也可以用来指定命名空间中的特定项目。例如,如果您只打算使用 std 命名空间中的 cout 部分,您可以使用如下的语句: #include <iostream> using std::cout; int main () { cout << "std::endl is used with std!" << std::endl; return 0; } 3.不连续的命名空间 命名空间可以定义在几个不同的部分中,因此命名空间是由几个单独定义的部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。 所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。下面的命名空间定义可以是定义一个新的命名空间,也可以是为已有的命名空间增加新的元素: namespace namespace_name { // 代码声明 } 4.嵌套的命名空间 在c++中,命名空间的使用是可以嵌套的。如下所示: namespace namespace_name1 { // 代码声明 namespace namespace_name2 { // 代码声明 } } 注意,引用父级命名空间并不能直接调用子空间里的变量,如下: #include<iostream> using namespace std; namespace first_space{ namespace second_space{ int a=0,b=1; } } using namespace first_space; int main(){ cout<<a<<" "<<b<<endl; //错误代码,a未定义 return 0; } 正确调用方式如下: #include<iostream> using namespace std; namespace first_space{ namespace second_space{ int a=0,b=1; } } using namespace first_space::second_space; int main(){ cout<<a<<" "<<b<<endl; return 0; }

优秀的个人博客,低调大师

java8学习:默认方法

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 在java8中接口引进了静态方法以及默认方法,通过默认方法,可以为接口方法提供默认实现,也就是说接口能提供方法的具体实现.因此实现接口的类如果不显示的提供该方法的具体实现,就会自动继承默认的实现 同时定义接口以及工具辅助类是java常用的一种模式,工具类定义了与接口实例协作的很多静态方法,由于静态方法现在可以存在接口内部,所以代码中的辅助类就没有了存在的必要,可以直接把这些静态方法转移到接口内部 不断演进的API 我们来说一下为什么会出现默认方法 假如有如下一个接口,你是类库的设计者,那么你写的接口是这样的 public interface Behavior { void eat(String foodName); } 然后你发布之后大火,你的用户是这样使用的 public class Dog implements Behavior { @Override public void eat(String foodName) { System.out.println("dog " + foodName); } } 之后你收到了很多意见,说这个行为接口并不丰富,行为不可能只有吃的行为,动物可是都有吃喝拉撒的行为啊! 现在你就遇到了问题,如果你将建议的接口添加入Behavior接口,然后发布,这时候你的用户只要更新API的版本,那么他就会遇到一个大麻烦,那么就是实现你在接口中定义的所有方法.这对用户来说是非常不好的.这也是默认方法产生的原因:它可以让你放心的改进接口,无须担心遗留代码的影响,这是因为实现更新接口的类都会自动的集成一个默认的方法实现 不同类型的兼容:二进制,源代码和函数行为 变更对java的影响大体可以分为三种类型的兼容:二进制级的兼容,源代码级的兼容,以及函数行为的兼容. 二进制级的兼容性表示现有的二进制执行文件能无缝持续链接和运行,比如,为接口添加一个方法就是二进制级的兼容,这种方式下,如果添加的新方法不被调用,接口已经实现的方法可以继续运行,不会出现错误 简单的说,源代码级的兼容性表示引入变化之后,现有的程序依然能够成功通过编译 函数行为的兼容性表示发生变更后,程序接受同样的输入能得到相同的结果 概述默认方法 默认方法就是用default修饰的方法,并像类中声明的其他方法一样包含方法体,并且只要类实现了这个包含默认方法的接口,他就会继承默认方法 java8中的抽象类和抽象接口区别:首先一个类只能继承一个抽象类,但是一个类可以实现多个接口,其次,一个抽象类可以通过实例变量保存一个通用状态,而接口是不能有实例变量的 默认方法的使用模式 可选模式 平常我们用类实现一个接口,接口中有很多方法需要我们重新定义,如果有用的方法还好,如果我们并用不到的方法,为了满足接口方法的实现规则,我们就必须在那放一个空方法实现,这也是多余的模板代码,我们可以将这类方法变更为默认方法以实现不必要的空实现 行为的多继承 行为的多继承值得是:类只能继承一个类,但是可以实现多个接口中的方法,这就是所谓的多继承,现在java8中有了方法的默认实现,那么我们的类就得到了来自不同接口的实现的功能 解决冲突的规则 一个类实现了多个接口,而多个接口中含有覆盖实现的方法,那么类会使用那个接口中的方法呢?如果是多个接口中的方法都是相同的方法签名呢? interface A{ default void say(){ System.out.println("A"); } } interface B extends A { @Override default void say() { System.out.println("B"); } } public class Dog implements B{ public static void main(String[] args) { new Dog().say(); //B } } 如果一个类使用相同的函数签名从多个地方继承了方法,通过三条规则可以进行判断 类中的方法优先级最高,类或父类中声明的方法的优先级高于任何声明为默认方法的优先级 如果无法依据第一条判断,那么就是子类的优先级更高:函数签名相同时,优先选择拥有最具体实现的默认方法的接口,即B继承了A,那么B更具体 如果还没办法判断,继承多个接口的类必须通过显示覆盖和调用期望的方法,现实的选择使用哪个默认方法的实现 如下 interface A{ default void say(){ System.out.println("A"); } } interface B extends A { @Override default void say() { System.out.println("B"); } } class D implements A{ } public class Dog extends D implements A,B{ public static void main(String[] args) { new Dog().say(); //B } } 依照类或父类中声明的方法的优先级高于任何声明为默认方法的优先级,那么就会优先选择D,那么D并没有覆盖掉say方法,但是他默认继承了A的方法,所以它会调用A的方法,但是他会选择更具体的实现,那么就是B,最终也是输出的B 菱形继承问题 interface A{ default void say(){ System.out.println("A"); } } interface B extends A { } interface C extends A{ } public class Dog implements B,C{ public static void main(String[] args) { new Dog().say(); //A } } 如上,其继承实现关系类似于菱形,Dog实现了B,C但是BC中只是继承了A中的默认方法,所以编译并不会出错,并且Dog也是使用此默认实现,所以输出A 如果我们将B加上覆盖实现呢? interface B extends A { default void say(){ System.out.println("B"); } } 现在会输出B,因为覆盖实现的方法更加具体 如果两个BC接口都覆盖实现了say方法呢? //B接口如上变动 interface C extends A{ default void say(){ System.out.println("C"); } } 这时候我们就会发现,Dog编译出错了,因为BC都有具体实现,并且都是一个级别的,都是具体实现了A的默认方法,Dog就不知道需要调用谁的方法了,这时候我们只能是在Dog中覆盖这个默认方法的实现了 public class Dog implements B,C{ public static void main(String[] args) { new Dog().say(); //dog } @Override public void say() { System.out.println("dog"); } } 如果BC接口只是定义的与A中say方法签名一样的抽象方法呢? interface A{ default void say(){ System.out.println("A"); } } interface B extends A { void say(); } interface C extends A{ default void say(){ System.out.println("C"); } } public class Dog implements B,C{ public static void main(String[] args) { new Dog().say(); //dog } @Override public void say() { System.out.println("dog"); } } 如上只要有一个接口有抽象方法,那么我们就还得按照接口中抽象方法必须实现的规则来 所以解决所有可能的冲突只需要三点 类或父类中显示声明的方法,其优先级高于任何默认方法,即自己实现的比默认的优先级高 如果上面的无法判断,方法签名又没有区别,那么选择提供最具体实现的默认方法的接口,即用接口的最具体的子类的实现 如果依旧有冲突,那么就只能在本类中重写覆盖默认方法了

优秀的个人博客,低调大师

JavaScript学习(十一)--数值处理对象

目录 Math对象 1.math对象的属性 2. Math对象的方法 Number对象 1.创建Number对象 2.Number对象的属性 (1)MAX_VALUE属性 (2)MIN_VALUE属性 (3)NEGATIVE_INFINITY属性 (4)POSITIVE_INFINITY属性 3.Number对象的方法 (1)toString()方法 (2)toFixed()方法 (3)toExponential()方法 (4)toPrecision()方法 Boolean对象 1.创建Boolean对象 2.Boolean对象的属性 (1)constructor属性 (2)prototype属性 3.Boolean对象的方法 (1)toString()方法 (2)valueOf()方法 Math对象 1.math对象的属性 例子: var piValue=Math.PI; //计算圆周率 var rootofTwo=Math.SQRT2; //计算平方根 2. Math对象的方法 例子: var result=Math.pow(value1,10); //计算一个数的10次方 var result=Math.round(value); //使用四舍五入函数计算最相近的整数值 随机产生指定位数的验证码。 <body> <script type="text/javascript" language="JavaScript"> function ran(digit){ /*自动生成验证码*/ var result=""; for(i=0;i<parseInt(digit);i++){ result=result+(parseInt(Math.random()*10)).toString(); } return result; } function deal(){ result.innerHTML="&nbsp;&nbsp;产生的验证码:"+ran(form.digit.value); } </script> <form name="form"> <input type="text" name="digit" /> <input type="button" value="生成" onclick="deal()"/> </form> <div id="result"> &nbsp;&nbsp;产生的验证码: </div> </body> Number对象 由于JavaScript使用简单数值完成日常数值的计算,因此,number对象很少被使用,当需要访问某些常量值时,如数字的最大或最小值、正无穷大或负无穷大时,该对象显得非常有用。 1.创建Number对象 number对象是原始数值的包装对象,使用该对象可以将数字作为对象直接进行访问。 语法:numobject=new Number(value) value:可选项。是新对象的数字值。如果忽略value,则返回值为0. 2.Number对象的属性 (1)MAX_VALUE属性 MAX_VALUE属性用于返回number对象的最大可能值。 语法:value=Number.MAX_VALUE; value:存储Number对象的最大可能值的变量。 例子: var max=Number.MAX_VALUE; document.write(max); (2)MIN_VALUE属性 MIN_VALUE属性用于返回number对象的最小可能值 语法:value=Number.MIN_VALUE value:存储Number对象的最小可能值的变量。 (3)NEGATIVE_INFINITY属性 NEGATIVE_INFINITY属性用于返回number对象的负无穷大的值。 语法:value=Number.NEGATIVE_INFINITY value:存储Number对象的负无穷大的值。 (4)POSITIVE_INFINITY属性 POSITIVE_INFINITY属性用于返回number对象的正无穷大的值。 语法:value=Number.POSITIVE_INFINITY value:存储Number对象的正无穷大的值。 3.Number对象的方法 (1)toString()方法 toString()方法可以把Number对象转换成一个字符串,并返回结果。 语法:Numberobject=.toString(radix) (2)toFixed()方法 toFixed()方法将number对象四舍五入为指定小数位数的数字,然后转换为字符串。 语法:Numberbject.toFixed(num) (3)toExponential()方法 toExponential()方法 利用指数计数法计算number对象的值,然后将其转换成字符串。 语法:number.toExponential(NUM) NUM:必选项。规定指数计数法中的小数位数 ,是0-20之间的值。 (4)toPrecision()方法 toPrecision()方法将number对象转换成字符串,并根据不同的情况选择定点计数法或指数计数法。 语法:number.toPrecision(num) NUM:必选项。规定指数计数法中的小数位数 ,是0-20之间的值。 Boolean对象 1.创建Boolean对象 Boolean对象是JavaScript的一种基本数据类型,是一个把布尔值打包的布尔对象。可以通过Boolean对象创建新的Boolean值。 语法:bool=new Boolean([boolValue]) bool:要赋值为Boolean对象的变量名。 boolValue:可选项。是新对象的初始Boolean值。如果忽略boolValue,或者其值为false、0、null、NaN或空字符串,则该Boolean对象的初始值为false;否则,初始值为true。 2.Boolean对象的属性 Boolean对象有constructor和prototype两个属性,下面分别进行介绍。 (1)constructor属性 constructor属性用于对当前函数的引用。 (2)prototype属性 prototype属性可以对对象添加属性和方法。 var newboolean=new Boolean(); Boolean.prototype.mark=null; newboolean.mard=1; alert(newboolean.mard); 3.Boolean对象的方法 Boolean对象有toString()和valueOf()两个方法。 (1)toString()方法 toString()方法用于将Boolean值转换为字符串。 语法:Boolean.toString() (2)valueOf()方法 valueOf()方法用于返回Boolean对象的原始值。 语法:Boolean.valueOf()

优秀的个人博客,低调大师

20.Swift学习之协议

协议 协议为方法、属性、以及其他特定的任务需求或功能定义一个大致的框架。协议可被类、结构体、或枚举类型采纳以提供所需功能的具体实现。满足了协议中需求的任意类型都叫做遵循了该协议。 协议的定义 协议的定义方式与类,结构体,枚举的定义都非常相似 protocol SomeProtocol { // 属性 // 方法 } 协议中的属性 不可以有默认值 必须设置是{get}或者{get set} ,注意:get与set之间是没有逗号的 必须设置为var 协议中的方法 可以定义普通方法也可以是mutating方法 方法不能有方法体 方法的参数不可以有默认值 protocol Pet { // 定义属性 var name: String {get set} var age: Int {get} // 定义方法 func feed(food: String) mutating func shout(sound :String); } 协议的遵守格式(实现协议) 格式 class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol { // 类的内容 // 实现协议中的方法 } 实现协议中的属性 此时属性可以设置默认值 协议中属性为可读可写的,可以直接声明为var类型就可以 协议中属性为可读属性,可以直接声明为let类型就可以,也可以声明为var类型 实现协议中的方法 可以为方法中的参数设置默认值 在结构体中,如果需要改变自身的值,需要在方法前面加mutating关键字。在协议的方法中添加mutating关键字,如果结构体来遵守协议,需要有mutating这个关键字,如果是类来遵守协议,mutating关键字就不需要了。 class Cat : Pet{ //属性可以设置默认值 //可读可写用var var name: String = "Dingding" //只读可以用let let age: Int = 10 func feed(food: String) { print("feed\(food)") } //方法参数可以有默认值 //类实现mutating方法要修改属性值时必须加不用加mutating func shout(sound: String = "miaomiao") { self.name = "Caicai" print("shout\(sound)") } } struct Dog : Pet{ var name: String var age: Int func feed(food: String) { print("feed\(food)") } //结构体实现mutating方法要修改属性值时必须加mutating mutating func shout(sound: String) { self.name = "Guaiguai" print("shout\(sound)") } } 协议之间的继承 protocol CrazySportProtocol { func jumping() } //继承协议 protocol SportProtocol : CrazySportProtocol { func playBasketball() func playFootball() } //此时的类必须所有方法都实现 class Person:SportProtocol{ func playBasketball() { print("playBasketball") } func playFootball() { print("playFootball") } func jumping() { print("jumping") } } 协议中方法的可选 方法一 定义协议 @objc protocol SportProtocol2 { // 该方法可选 @objc optional func playBasketball() func playFootball() } 遵守协议 class Person : SportProtocol2 { var name : String? var age : Int = 0 // 实现协议中的方法,此时可以不实现协议中的可选方法,当然也可以实现 func playBasketball() { print("人在打篮球") } } 方法二 扩展协议 protocol SomeProtocol { func requiredFunc() func optionalFunc() } extension SomeProtocol { func optionalFunc() { print("optionalFunc扩展中实现") } } class SomeClass: SomeProtocol { func requiredFunc() { print("requiredFunc具体类中实现") } } 协议的运用——代理模式 //1.定义一个协议,规定需要完成的任务 protocol BuyTicketProtocol { func buyTicket() } //2.让具体的类或者结构体实现协议,将任务具体化 class Assist : BuyTicketProtocol{ func buyTicket() { print("助手去买票") } } class HN : BuyTicketProtocol{ func buyTicket() { print("黄牛去买票") } } //3.委托方申明一个属性(遵循协议),然后在真正需要完成任务的时候调用属性来完成 class Person { // 1.定义协议属性 var delegate : BuyTicketProtocol // 2.自定义构造函数 init (delegate : BuyTicketProtocol) { self.delegate = delegate } // 3.行为 func goToBeijing() { print("找代理买票") delegate.buyTicket() print("拿到票去北京") } } let p = Person(delegate: HN()) p.goToBeijing() let p2 = Person(delegate: Assist()) p2.goToBeijing()

优秀的个人博客,低调大师

2018-11-12学习笔记

Android 实战 | 使用揭露动画(Reveal Effect)做一个丝滑的Activity转场动画 揭露动画(Reveal Effect)实现时的注意事项(附上bug-logcat) boolean java.lang.String.equals(java.lang.Object)' on a null object reference java.lang.NullPointerException: Attempt to invoke virtual method 'int android.content.Intent.getI... 其他 ROS_机器人urdf建模仿真实践 基于VM14+ Ubuntu 16.04安装VMware Tools(VM同主机file交互的工具)以及使用的骚操作 解决 | 此数据库文件跟当前sql server实例不兼容 & sql server2008无法连接到(local) 解决 | VS 2015右键项目添加新项中没有web窗体等选项

优秀的个人博客,低调大师

java8学习:引入stream

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 这一篇内容要讲的是流,关于流的概念,流的内部迭代跟外部迭代的区别之类的偏概念性的问题,下一篇在细讲流到底是什么用 那么说到流,我们自然就会想到水,这就涉及到水源头是哪里,水怎么流过来的,水会被我们的桶收集起来,还是说用水杯收集起来,那么问题就一下子出现了三个 流的源头是哪里 流的源头包括集合,数组或者一些输入输出资源,但是需要注意的是,从有序集合生成流时会保持原有的数据,从列表生成的流,其元素数据与列表一致 流是怎么个处理过程 这其实就要设计到用到了具体的api了,下面会说到 流的收集 无非就是收集成集合等一些等存储数据的数据结构中 流和集合作对比 一点很清楚的就是,流是来做计算的,而集合是用来存储的,这个应该很容易理解 还有一个就是:我们需要看一部电影,那么无非就是两种在线看和下载下来看,那么在线看就属于流模式,而整个资源下载下来看就属于集合模式了,所以从简单的说集合与流之间的差异就在与什么时候计算。集合是一个内存中的数据结构,它包含了所有值,就比如我们使用的list,不管添加还是删除他总是在内存中操作的,并且它是每个元素先计算出来再添加到集合的,而流呢?他就像我们在线看电影一样,不需加载全部的数据,剧情无聊快进的时候,流的处理方式就是加载你点击的时间点之后的几帧来供你观看,这就是他们的区别 好了扯了一大堆概念,让我们来看看集合和流处理数据的方式 我们利用下面这个类的结构来编写代码 @Data public class Dish { private final String name; private final boolean vegetarian; //是否是素菜 private final int calories; //卡路里 private final Type type; private enum Type{ MEAT,FISH,OTHER; } public Dish(String name, boolean vegetarian, int calories, Type type) { this.name = name; this.vegetarian = vegetarian; this.calories = calories; this.type = type; } } 好了让我们创建一个集合 List<Dish> menu = Arrays.asList( new Dish("apple",true,50, Dish.Type.OTHER), new Dish("chicken",false,350, Dish.Type.MEAT), new Dish("rich",true,150, Dish.Type.OTHER), new Dish("pizza",true,350, Dish.Type.OTHER), new Dish("fish",false,250, Dish.Type.FISH), new Dish("orange",true,70, Dish.Type.OTHER), new Dish("banana",true,60, Dish.Type.OTHER)); 集合操作:找出卡路里最低排名的前三位 @Test public void test() throws Exception { menu.sort(new Comparator<Dish>() { @Override public int compare(Dish o1, Dish o2) { return o1.getCalories() - o2.getCalories(); } }); for (int i = 0; i < 3; i++) { System.out.println(menu.get(i)); } } 流操作:找出卡路里最低排名的前三位 @Test public void test() throws Exception { List<Dish> collect = menu .stream() .sorted(Comparator.comparing(Dish::getCalories)) .limit(3) .collect(Collectors.toList()); for (Dish dish : collect) { System.out.println(dish); } } 观察上面两种,肯定是流操作比较好一些,因为它操作的每一步都很清楚的告诉开发者他的流在干什么,如上就是流和集合的一个简单对比 如上其实也反映了两个:内部迭代和外部迭代,流就属于内部迭代,集合的操作的方法就是外部迭代 内部迭代就是按照我们的意思,类似SQL似的查询操作,比如取前三啊那就是limit(3),然后他会根据你的查询条件自动的去遍历你的集合,这样就省去自己去一步步的写逻辑了 外部迭代自己理解的就是需要开发者手动编写遍历逻辑 那么流是一个一次性的,所以我们看如下 Stream<Dish> limit = menu.stream() .sorted(Comparator.comparing(Dish::getCalories)) .limit(3); List<Dish> collect1 = limit.collect(Collectors.toList()); //IllegalStateException: stream has already been operated upon or closed List<Dish> collect2 = limit.collect(Collectors.toList()); 上面就充分说明了,流只能遍历一次。当遍历一次之后这个流就被消费掉了,如果重新需要,那么需要从源头那再获取个stream 我们看下面的代码 Stream<Dish> limit = menu.stream() .sorted(Comparator.comparing(Dish::getCalories)) .limit(3); System.out.println(limit);//java.util.stream.SliceOps$1@436e852b List<Dish> collect1 = limit.collect(Collectors.toList()); //结果 这段代码就可以说明了,流是一种类似懒加载模式的,只有触发终端操作,那么这个流才会开始启动遍历数据,如上我们一直到limit(3)这都是流的中间操作,流的中间操作是不会产生数据的,只有出发了collect方法这个终端方法才会开始流的遍历工作,当然中间操作不止limit,sorted,终端操作也不止collect,这一篇只是简单的引入一下流而已,下一篇内容将会讲stream的使用 好了这一篇内容就介绍到这,主要介绍了流的概念,流和集合的区别,内外迭代和流的中间操作以及终端操作,还有重要的一点就是流是一次性的

优秀的个人博客,低调大师

21.Swift学习之扩展

扩展 为现有的类、结构体、枚举类型、协议添加了新功能。扩展和 Objective-C 中的分类类似。 扩展可以: 添加计算属性; 定义方法; 提供新的构造函数; 使现有的类型遵循某协议 Swift中使用extension关键字实现扩展 语法 extension SomeType { // new functionality to add to SomeType goes here } 扩展可以使已有的类型遵循一个或多个协议。在这种情况下,协议名的书写方式与类或结构体完全一样: extension SomeType: SomeProtocol, AnotherProtocol { // implementation of protocol requirements goes here } 扩展计算属性 扩展可以向已有的类型添加计算实例属性和计算类型属性。 extension Double { var km: Double { return self * 1_000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1_000.0 } var ft: Double { return self / 3.28084 } } 25.0.km 25.0.m 25.0.cm 25.0.mm 3.0.ft 扩展构造函数 扩展可向已有的类型添加新的初始化器 extension CGRect{ init(center: CGPoint, size: CGSize) { let originX = center.x - size.width * 0.5 let originY = center.y - size.height * 0.5 self.init(x: originX, y: originY, width: size.width, height: size.height) } } let centerRect = CGRect(center: CGPoint(x: 100.0, y: 100.0), size: CGSize(width: 100.0, height: 100.0)) 扩展方法 扩展可以为已有的类型添加新的实例方法和类型方法。 extension Int { func repetitions(task: () -> Void) { for _ in 0..<self { task() } } } 3.repetitions { print("Hello!") } 扩展mutating方法 扩展结构体,如果要修改里面的值,必须在方法面前加上mutating extension Int { mutating func square() { self = self * self } } //必须用变量,因为它的值要被修改 var someInt = 3 someInt.square() 使现有的类型遵循某协议 class ViewController : UIViewController{ } extension ViewController : UITableViewDataSource{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return UITableViewCell() } } 面向协议编程 针对某个需要实现的功能,可以使用协议定义出接口,然后利用协议扩展提供默认的实现。需要这个功能,只需要声明遵守了这个协议即可,遵守某个协议的对象调用协议声明的方法时,如果类本身没有提供实现,协议扩展提供的默认实现会被调用。 案例一 protocol Eat { func eat() } class Person: Eat { func eat() { print("吃饭了") } } var p = Person() p.eat() 改进 extension Eatable { func eat() { print("吃饭了") } } class Person: Eatable { } var p = Person() p.eat() 再次修改 class Person: Eatable { func eat() { print("人要吃饭了") } } var p = Person() p.eat() 案例二 protocol Coder { var haveFun:Bool {get set} var ownMoney:Bool {get set} } protocol Swifter { var codingLevel:Int {get set} } struct CoderA : Coder { var name:String var haveFun: Bool var ownMoney: Bool } struct CoderB : Coder, Swifter { var name:String var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 3 } struct CoderC : Coder, Swifter{ var name:String var haveFun: Bool = true var ownMoney: Bool = true var codingLevel: Int = 5 } 可以发现CoderB与CoderC有冗余 改进 protocol Coder { var haveFun:Bool {get set} var ownMoney:Bool {get set} } protocol Swifter { var codingLevel:Int {get set} } //where限定条件 extension Coder where Self:Swifter { var haveFun:Bool { return true} var ownMoney:Bool { return true} } struct CoderA : Coder { var name:String var haveFun: Bool var ownMoney: Bool } struct CoderB : Coder, Swifter { var name:String var haveFun: Bool var ownMoney: Bool var codingLevel: Int = 3 } struct CoderC : Coder, Swifter{ var name:String var haveFun: Bool var ownMoney: Bool var codingLevel: Int = 5 }

优秀的个人博客,低调大师

Scala学习笔记(1)-环境搭建

Scala是一种多范式的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。scala可以和java程序无缝拼接,因为scala文件编译后也是成为.class文件,并且在JVM上运行,有下下一代Java之称,当然要有Java今天的阵势还有很长很长的一段路要走。 Scala的几个主要特性 1.面向风格:Scala中的每个值都是一个对象,包括基本数据类型(java中基本类型不是对象)在内,连函数也是对象。 2.函数式风格:高阶函数(Higher-Order Function)、局部套用(Currying)、嵌套函数(Nested Function)、序列解读(Sequence Comprehensions)等等。 3.Scala是静态类型的,这就允许它提供泛型类、内部类、甚至多态方法(Polymorphic Method) 4.Scala可以与Java互操作:它用scalac这个编译器把源文件编译成Java的class文件(即在JVM上运行的字节码)。你可以从Scala中调用所有的Java类库,也同样可以从Java应用程序中调用Scala的代码。它也可以访问现存的数之不尽的Java类库,这让(潜在地)迁移到Scala更加容易。 1.安装Scala,这个不用多说 Scala目前最新的版本为2.11.8,下载地址http://www.scala-lang.org/,我下载的.msi文件,直接安装完毕自动添加了path 2.安装IDE (1)直接下载ScalaIDE,安装完后就可以直接使用。 (2)已安装有Eclipse的,可以安装scala支持插件,支持的eclipse版本是3.8-4.3(Juno and Kepler) 插件地址 http://download.scala-ide.org/sdk/helium/e38/scala211/stable/site 其他版本:http://scala-ide.org/download/prev-stable.html 3.写一段代码测试一下 package com.demo object Demo {//注意这里是object 不是 class 喔,两者区别后面会讲到。 def main(args: Array[String]): Unit = { println("hello scala!") println("hello world!");//分号可选要不要 } } 本文来自云栖社区合作伙伴“开源中国” 本文作者:山海经 原文链接

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册