首页 文章 精选 留言 我的

精选列表

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

redis学习之redis的安装和简介

redis简介 Redis是一个开源的,高性能的,基于键值对的缓存与存储系统,通过设置各种键值数据类型来适应不同场景下的缓存与存储需求。同时redis的诸多高层级功能使其可以胜任消息队列,任务队列等不同角色。 存储结构 Redis是REmote Dictionary Server(远程字典服务器)的缩写,它以字典结构存储数据,并允许其他应用通过TCP协议读写字典中的内容,目前为止redis支持的键值数据类型如下:字符串类型,散列类型,列表类型,集合类型,和有序集合类型。其中一个字符串类型键值允许存储的数据最大容量为521M. 内存存储与持久化 Redis数据库中的所有数据都存储在内存中。在一台普通的笔记本电脑上,Redis可以在一秒内读写超过10万个键值。 数据存储在内存也有问题比如断电。redis还提供了持久化的存储,既可以将内存的数据异步写入应哦按,同时不影响继续 提供服务。 功能丰富 Redis可以为每个键设置生存时间,生存时间到后期会自动删除,这一功能可以利用redis作为缓存系统来调用。 除此之外,redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以容易地实现一个高性能的优先级队列,同时在更高层上,redis还支持"发布/订阅"的消息模式,可以基于此构建聊天室。 redis的安装 参考windows安装redis redis命令行客户端 通过redis-cli向redis发送命令, 通过-h和-p自定义地址和端口号$redis-cli-h127.0.0.1-p6379 通过ping命令测试连接是否正常 $redis-cliPING####状态回复 PONG####错误回复 如果上述命令不存在或者存在格式错误,会返回以error开头的错误。如reids>ERRORCOMMEND 输出 (error)ERRunknowcommand'ERRORCOMMEND' 获取先输入redis-cli进入交互模式,然后自由输入命令,例如PING. 整数回复 返回递增后的键值,类似mysql最后的索引值 依次执行以下命令redis-cli 127.0.0.1:6379>setfootbarOK 127.0.0.1:6379>INCRfoo (integer)1 127.0.0.1:6379>setfootbarOK 127.0.0.1:6379>INCRfoo (integer)2 可以看到每次插入一条数据返回值都跟着变化。 字符串回复 127.0.0.1:6379>setfootbarOK 127.0.0.1:6379>getfoo "bar" 127.0.0.1:6379>setfoobananaOK 127.0.0.1:6379>getfoo "banana" 127.0.0.1:6379> 可以看到get命令可以获取foo的最新的键值。 字符串多行回复 127.0.0.1:6379>KEYS*1)"proxies"2)"foo"3)"foot" 返回键名1是我之前执行的,3是之前foo打错了执行的。keys命令需要便利redis中的所有键,当键的数量较多时会影响性能,不建议生产环境中使用。 多行数据库 redis提供了多个来存储数据的字典,每个字典类型mysql的数据量,每个数据库对外都是以0开始递增,redis默认支持16个数据库,客户端连接到服务端时,redis默认使用0进行操作数据库,使用select可以根据数据库。比如选择1号数据库: redis-cli 127.0.0.1:6379>select1OK 127.0.0.1:6379[1]>getfoo (nil) 127.0.0.1:6379[1]> redis不支持自定义数据库的名字,每个数据库必须以编号命名。比如可以使用0号数据库存储某个应用生产环境的数据,1号数据库存储测试环境中的数据,需要注意的是不同的应用应该使用不同的redis实例redis也不支持为每个数据库设置不同的访问密码。 最重要的是redis实例中所有数据库的数据并不是完全隔离的,比如FLUSHALL可以清空一个redis实例中所有数据库中的数据。。由于redis非常轻量级,一个空的redis实例占用内存只有1MD左右,所以不用担心多个redis实例会额外占用很多内存。 几个基础命令 1.keys 见上面的例子 2.判断一个键是否存在 exists key 如果存在返回1 ,不存在返回0 0.0.1:6379>existsfoo (integer)1 127.0.0.1:6379>existsfoo2 (integer)0 127.0.0.1:6379>existsfoot (integer)1 127.0.0.1:6379> 3.删除键 del key [key …] 可以删除一个或者多个空格间隔,返回值是删除的个数。del命令不支持通配符。 127.0.0.1:6379>setf11OK 127.0.0.1:6379>setf31OK 127.0.0.1:6379>setf21OK 127.0.0.1:6379>keys* 1)"key" 2)"f1" 3)"proxies" 4)"f2" 5)"foot" 6)"foo" 7)"f3" 127.0.0.1:6379>delf1 (integer)1 127.0.0.1:6379>delf2f3 (integer)2 127.0.0.1:6379> 3.获取键值的数据类型 type key type命令用来获取键值类型,返回值可能是string,hash,list,set,zset(有序集合)。 127.0.0.1:6379>settest1OK 127.0.0.1:6379>typeteststring 127.0.0.1:6379>lpushtest22 (integer)1 127.0.0.1:6379>typetest2list 127.0.0.1:6379> lpush命令是向指定的列表类型键中增加一个元素,如果不存在则创建。后面详解。 读取键值 get key 根据键获取其值。 127.0.0.1:6379>getfo (nil) 127.0.0.1:6379>getfoo "banana" 127.0.0.1:6379> 不存在的时候返回nil. 递增数字 INCR key 增加指定的整数 INCRBY key increment incrby和incr命令效果差不多,区别是incrby可以指定增加的数字 127.0.0.1:6379>incrbybar2 (integer)2 127.0.0.1:6379>incrbybar5 (integer)7 127.0.0.1:6379>incrbar (integer)8 127.0.0.1:6379>incrbar (integer)9 127.0.0.1:6379> 增加指定的浮点数 incrbyfloat key inrement 这个命令类似上面两个只不过是可以传递一个浮点数而已 127.0.0.1:6379>incrbyfloatbar3.14 "12.140000000000001" 127.0.0.1:6379>incrbyfloatbar3.14e+9 "3140000012.1399999" 127.0.0.1:6379> 减少指定的整数 有增加就有减少 decr和decrby和增加的用法一样,只不过是键值递减。 decrby key 4相当于incrbu key -4 向尾部追加值 向键值的末尾加字符串,如果不存在就是相当于set key value 127.0.0.1:6379>appendbar"345" (integer)21 127.0.0.1:6379>getbar "3140000012.1399999345" 127.0.0.1:6379> 127.0.0.1:6379>appendasd"hellodj" (integer)8 127.0.0.1:6379>getasd "hellodj" 127.0.0.1:6379> 获取字符串长度 STRLEN key 返回键值长度,不存在返回0. 127.0.0.1:6379>setkey"￀￷ᄎᆭ"OK 127.0.0.1:6379>strlenkey (integer)4 127.0.0.1:6379>setkey"ᅣ ̄채"OK 127.0.0.1:6379>strlenkey (integer)4 127.0.0.1:6379> 同时设置多个键值 Mget key/mset key value mget/mset和get/set相似,前者可以获取/设置多个值。 (integer)4 127.0.0.1:6379>mgetbarfoo 1)"3140000012.1399999345" 2)"banana" 127.0.0.1:6379>mseta1b2OK 127.0.0.1:6379> 位操作 getbit key offset setbit key offset value bitcount key [start][end] bitop operation destkey key [key ….] 一个字节由8个二进制位组成,redis提供了以上四个命令可以直接对二进制进行操作。

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

牛客网学习笔记-day01

Java修饰符大小 public>protected>default>private final方法不等同于private方法 虽然类中的private方法都隐式地指定为final,但是二者并不是等同的。private是访问权限修饰符,用于控制外界对类内部成员的访问,private方法只能在类的内部访问,而final方法可以在类外部访问 final修饰类,表示类不可被继承 final修饰变量,表示变量不可更改 final修饰方法,表示方法不可被覆盖 方法重写原则(两同两小一大) 方法名相同,参数类型相同 子类返回类型小于等于父类方法返回类型 子类抛出异常小于等于父类方法抛出异常 子类访问权限大于等于父类方法访问权限 IO流 System.out.println含义 System是java.lang包下的一个类 out是System类的一个final静态成员(public final static PrintStream out = null;) println()是PrintStream类的实例方法 静态代码块、构造方法、代码块执行顺序 父类静态代码块->子类静态代码块->父类非静态代码块->父类构造方法->子类非静态代码块->子类构造方法 原因分析:当实例化子类对象是,首先加载父类的class文件到内存中,静态代码块随着类的创建而执行,所以父类静态代码块最先被执行,子类class文件再被加载,子类静态代码块被执行;实例化子类对象要先调用父类的构造方法,而调用父类构造方法前会先调用父类的非静态代码块 匿名内部类 创建格式: new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 } 使用匿名内部类时,必须继承一个类或实现一个接口 匿名内部类由于没有名字,因此不能定义构造函数 匿名内部类不能含有静态成员变量和静态方法 匿名内部类的方法不能是抽象的

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

Python零基础学习笔记(十七)—— for 语句

''' for 语句,是一种循环语句 格式: for 变量名 in 集合: 语句 逻辑:按顺序取“集合”中的每个元素赋值给“变量”,再去执行语句 如此循环往复,直到取玩“集合”中的元素为止 ''' for i in [1,2,3,4,5]: print(i) ''' num = int(input()) if num in [1, 2, 3, 4, 5]: print("你输入的数字,我也有不信你看:%d"% num) ''' ''' range([start,] end[, step])函数 列表生成器 start 默认为0,step默认为1 功能:生成数列 ''' a = range(12) print(a) for i in range(12): print(i) for c in range(1, 20, 3): print(c) #同时遍历下标和元素 enumrate 枚举遍历器 for index, m in enumerate([1,2,3,4,5]): #index,m = 下标, 元素 print(index, m) #1+2+3+...+100 sum = 0 for n in range(101): sum += n print(sum) 执行结果 1 2 3 4 5 range(0, 12) 0 1 2 3 4 5 6 7 8 9 10 11 1 4 7 10 13 16 19 0 1 1 2 2 3 3 4 4 5 5050

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

java8学习:新的日期使用

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 最开始java 1.0时代,开始使用Date时间类,相当难用,他是以1900年起始,月份是从0开始的,如果你要表示2018年11月25日,那么就要这样 Date date = new Date(118,10,25); System.out.println(date.toLocaleString()); //2018-11-25 0:00:00 之后Date大多数方法已经废弃,却而代之的是Calendar类,但是这个类的月份依旧是从0开始的,但是年份不是从1900开始的,但是解析日期的DateFormat方法只在Date中有,并且他不是线程安全的 Date和Calendar都是可变的,这将带来很多麻烦,java8中在java.time中整合了很多Joda-Time的特性,Joda-Time之前是第三方类库 使用LocalDate和LocalTime 从类名就可以看出,LocalDate是表示年月日,而LocalTime是表示时分秒 LocalDate使用 LocalDate date = LocalDate.of(2018,11,25); int year = date.getYear(); //2018 Month month = date.getMonth(); // NOVEMBER int dayOfMonth = date.getDayOfMonth(); //25 DayOfWeek dayOfWeek = date.getDayOfWeek(); //SUNDAY int i = date.lengthOfMonth(); //30 boolean leapYear = date.isLeapYear(); //false //获取现在时间 LocalDate now = LocalDate.now(); //2018-11-25 除了getxxx方法,还可以使用TemporalField参数给get方法获取相同的信息 LocalDate localDate = LocalDate.of(2018, 11, 25); int year = localDate.get(ChronoField.YEAR); int month = localDate.get(ChronoField.MONTH_OF_YEAR); int dayofweek = localDate.get(ChronoField.DAY_OF_WEEK); 如上的ChronoField是TemporalField的实现 LocalTime的使用 LocalTime time = LocalTime.of(8,34,00); int hour = time.getHour(); //8 int minute = time.getMinute(); //34 int second = time.getSecond(); //0 int nano = time.getNano(); //0 LocalDate和LocalTime的解析 LocalTime time = LocalTime.parse("08:24"); LocalDate date = LocalDate.parse("2018-11-25"); 解析不了会出DateTimeParseException 合并日期和事件 就是LocalDateTime类,结合了上面两个类,可以同时表示年月日和时分秒 //LocalDateTime基本使用 LocalDateTime localDateTime = LocalDateTime.of(2018,11,25,8,37); //创建LocalDate对象 LocalDate localDate = LocalDate.now(); //调用atTime可以传入具体时分秒,构成LocalDateTime LocalDateTime time1 = localDate.atTime(8, 37); //创建LocalTime对象 LocalTime localTime = LocalTime.now(); //调用atDate,传入具体年月日对象,构成LocalDateTime LocalDateTime localDateTime1 = localTime.atDate(localDate); //从LocalDateTime中可以获取LocalDate和LocalTime LocalDate date = localDateTime.toLocalDate(); LocalTime time = localDateTime.toLocalTime(); Instant 以1970年1月1日0时0分0秒开始计算的 Instant instant = Instant.ofEpochSecond(20); //1970-01-01T00:00:20Z Instant.ofEpochSecond(20, 1000000000);//1970-01-01T00:00:21Z 如上的ofEpochSecond方法,第一个参数是以秒为单位的,然后增强版本,是以纳秒为单位的,其实第二个方法就是在1970-1-1-00:00:00时间上加上了21秒而已 也有now方法获取当前时间戳 Duration和Period 取两个时间之间的差值 LocalTime time1 = LocalTime.of(8,00); LocalTime time2 = LocalTime.of(9,00); Duration between = Duration.between(time1, time2); //PT1H LocalTime,LocalDateTime,Instant可以用于Duration,Duration适用于以秒和纳秒,所以就不能向其传入LocalDate LocalDate date1 = LocalDate.of(2018,7,7); LocalDate date2 = LocalDate.of(2018,8,10); Period between = Period.between(date1, date2); //P1M3D 当然他们不仅限于计算差值,还可以创建对象以代表具体的时间值 Duration duration = Duration.ofMillis(3); System.out.println("duration = " + duration);//duration = PT0.003S Period period = Period.ofDays(10); System.out.println("period = " + period);//period = P10D 对于其他的方法,大家可以查询文档即可:java8 api文档 对于以上的介绍目前为止日期对象都是不可变的,这是考虑函数式编程以及线程安全而做的决定 操纵解析和格式化日期 创建LocalDate的修改版 LocalDate date = LocalDate.of(2018, 4, 4); //2018-4-4 LocalDate date1 = date.withYear(2014);//2014-4-4 LocalDate date2 = date1.withMonth(6);//2014-6-4 LocalDate date3 = date2.withDayOfMonth(6);//2014-6-6 也可以这样 LocalDate date = LocalDate.of(2018, 4, 4); //2018-4-4 LocalDate date1 = date.minusYears(4); //2014-4-4 LocalDate date2 = date1.plusMonths(8);//2014-12-4 LocalDate date3 = date2.plusDays(10);//2014-12-14 需要注意的是,即使对一个时间对象调用方法,但是该对象是不会发生改变的,只是返回一个新对象,如下 LocalDate date = LocalDate.of(2018, 4, 4); //2018-4-4 LocalDate date1 = date.plusYears(2).with(ChronoField.MONTH_OF_YEAR, 12).plusDays(10); date.plusYears(12); System.out.println(date);//2018-4-4 System.out.println(date1);//2020-12-14 使用TemporalAdjuster 当我们遇到复杂情况的时候,比如调整时间到下个周日之类的要求,我们就需要自定义一个TemporalAdjuster对象,更加灵活的处理日期 java8已经预定义好一些TemporalAdjuster了,可以通过工厂类访问他们 LocalDate date = LocalDate.of(2018, 11, 26); //2018-11-26 周1 LocalDate date1 = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); //下个周日是2018-12-2 LocalDate date2 = date1.with(TemporalAdjusters.lastDayOfMonth()); //2018-12-31 十二月的最后一天 其他工厂方法请自己查看java api获取 TemporalAdjuster是一个函数式接口,定义如下 @FunctionalInterface public interface TemporalAdjuster { Temporal adjustInto(Temporal temporal); } 如上传入一个Temporal,返回一个Temporal,也就是说,实现的逻辑在于怎样把传入的Temporal转换为另一个需要的Temporal 定制TemporalAdjuster 创建类实现TemporalAdjuster接口 /** * 需求:返回下一个工作日,如果日期在周一到周五之间,就返回下一天就好,如果是周五六日就需要返回下周一的日期 */ public class NextWorkingDay implements TemporalAdjuster { @Override public Temporal adjustInto(Temporal temporal) { //得到参数中是这周的第几天 int day = temporal.get(ChronoField.DAY_OF_WEEK); //根据第几天构造出DayOfWeek枚举类,容易观察,当然也可以不用构造 //如果不够再下面的判断相等直接改成上面的day就行了 DayOfWeek dayOfWeek = DayOfWeek.of(day); //需要在参数的基础上增加几天 int dayNeedAdd = 1; //如果是周五,就需要推后三天才是周一 if (dayOfWeek == DayOfWeek.FRIDAY){ dayNeedAdd = 3; } //如果是周六,就需要推后两天才是周一 if (dayOfWeek == DayOfWeek.SATURDAY){ dayNeedAdd = 2; } //如果是周日或者当天就是在周一到周五之间的,直接加一就可以,即返回下一天 return temporal.plus(dayNeedAdd, ChronoUnit.DAYS); } } 上面说此接口是函数式接口,当然就可以使用Lmabda传入了,使用如下 LocalDate date = LocalDate.of(2018, 11, 25);//周日 LocalDate nextWorkDay = date.with(new NextWorkingDay()); //2018-11-26 使用lambda LocalDate date = LocalDate.of(2018, 11, 25);//周日 LocalDate nextWorkDay = date.with(temporal -> { //具体实现是把上面的实现类NextWorkingDay内实现的方法体贴进来就行了 }); 也可以这样 LocalDate date = LocalDate.of(2018, 11, 25);//周日 TemporalAdjuster nextWorkDay = TemporalAdjusters.ofDateAdjuster(temporal -> { //具体实现是把上面的实现类NextWorkingDay内实现的方法体贴进来就行了 }); LocalDate date1 = date.with(nextWorkDay); 如上是一个静态方法,传入一个UnaryOperator函数式接口的实现即可,就能够返回一个TemporalAdjuster对象,然后传入with方法即可 日期解析 java.time.format包就是解析日期格式化日期的,最重要的是DateTimeFormatter类,他有一些预定义常量 LocalDate date = LocalDate.of(2018, 8, 8); String format = date.format(DateTimeFormatter.BASIC_ISO_DATE);//20180808 String format1 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);//2018-08-08 也可以通过指定解析模式来解析Sring时间字符串 LocalDate parse = LocalDate.parse("20180808", DateTimeFormatter.BASIC_ISO_DATE); //2018-08-08 LocalDate parse1 = LocalDate.parse("2018-08-08", DateTimeFormatter.ISO_LOCAL_DATE); //2018-08-08 与之前的DateFormat相比,DateTimeFormatter是线程安全的 按照指定格式创建解析器 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM-dd"); LocalDate date = LocalDate.of(2018, 12, 6); //按照指定格式返回时间字符串 String format = date.format(formatter); System.out.println("format = " + format); //2018/12-06 //根据指定的解析格式解析指定时间字符串 LocalDate parse = LocalDate.parse(format, formatter); System.out.println("parse = " + parse); //2018-12-06 创建一个更加复杂的解析器 DateTimeFormatter builder = new DateTimeFormatterBuilder() .appendText(ChronoField.DAY_OF_MONTH) //首先解析的是一个月的第几天 .appendLiteral("(") //分隔符 .appendText(ChronoField.MONTH_OF_YEAR) //一年的第几个月 .appendLiteral("+") //分隔符 .appendText(ChronoField.YEAR) //年份 .parseCaseInsensitive() //开始解析,不区分大小写 .toFormatter(Locale.CHINA); //按照哪个国家的方言开始解析 LocalDate date = LocalDate.of(2018, 2, 25); String format = date.format(builder); System.out.println("format = " + format); //25(二月+2018 到这里,我们介绍了时间类的使用和解析,以及自定义如何实现自己的日期转换逻辑,至于本书剩下的时区和计算时区的偏差,本文不再记录

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

java8学习:Optional的简单使用

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 如下代码 public class Person { private Car car; public Car getCar() { return car; } } public class Car { private Insurance insurance; public Insurance getInsurance() { return insurance; } } public class Insurance{ private String name; public String getName() { return name; } } //将要使用的代码 public String getCarInsuranceName(Person person){ return person.getCar().getInsurance().getName(); } 如上代码如果使用,如果某个Person没有车,那么就会引发空指针异常,在平常我们使用if来去判断的,比如 public String getCarInsuranceName(Person person){ if (null != person){ Car car = person.getCar(); if (null != car){ Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName(); } } } return "UnKnow"; } 或者更容易读的是这样的,避免了if的嵌套难以阅读 public String getCarInsuranceName(Person person){ if (person == null) { return "UnKnow"; } Car car = person.getCar(); if (car == null){ return "UnKnow"; } Insurance insurance = car.getInsurance(); if (insurance == null) { return "UnKnow"; } return insurance.getName(); } 如上null的解决办法使用中的,并且不容易阅读,java8使用了Optional来解决null问题 Optional只能包含一个对象,对象存在的时候,Optional只是对对象的简单封装,如果没有对象,那么缺失的值被建模成一个空的Optional对象,有方法Optional.empty()返回 null和Optional的区别:null一定会触发空指针异常,而Optional.empty()就没有事,因为他是一个有效对象,是Optional 的单一实例. 使用Optional重新定义bean对象 public class Person { private Optional<Car> car; public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance; public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance{ private String name; //公司肯定有名字 public String getName() { return name; } } 上面中Person中的car类型是Optional,很明确的表达了Person可能有car对象也可能没有,同样对car的引用做了保证,有car的话就是car对象,没有car 的话就是Optional.empty() Insurance中name并没有加Optional,因为公司肯定是有名字的,如果name为空只能代表参数是错误的,而这里如果加上Optional只能掩盖错误发生 Optional的创建 空对象:Optional.empty() 依靠一个非空对象创建Optional:Optional.of(notnullobj),如果notnullobj是一个空对象,那么就会抛出空指针异常 可接受null对象的Optional:Optional.ofNullable(car),car对象可以是空对象也可以不是空对象,如果是空对象则得到一个空的Optional 使用map从Optional中提取和转换值 String name = null; if (insurance != null){ name = insurance.getName(); } 如上是原来的提取的代码,先判断在取值,避免空指针,如下使用Optional Optional<String> name = Optional.ofNullable(insurance).map(Insurance::getName); map函数会应用于流的每个元素上,然后返回name,可以把Optional看作是一个特殊的集合数据,至多包含一个元素,如果insurance包含值,那么就交给map处理,否则返回空Optional,就什么也不做 本文开头提到的这样一连串的调用,怎么用Optional解决呢? //原来 public String getCarInsuranceName(Person person){ return person.getCar().getInsurance().getName(); } 我们是用如下代码可不可以呢 ? public String getCarInsuranceName(Optional<Person> person){ person.map(Person::getCar) .map(Car::getInsurance) .map(Insurance::getName); } 如上代码是编译通过不了的,因为person对象是一个Optional对象,那么他调用map将会返回一个Optional>,这显然是错误的 之前我们在Stream遇到同样的问题,当时是用flatMap解决的,在这同样适用,如下 public String getCarInsuranceName(Optional<Person> person){ return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknow"); } 如上我们很清楚的就可以知道哪些对象可能是null,并且省去了if语句的平判断,在最后orElse:如果map得到的是null,那么就会有默认的UnKnow替代null,以防止发生空指针 Optional无法序列化 为什么? 如上代码中我们展示了使用Optional去构建bean,将允许缺失或者暂时无定义的变量值用特殊的形式标记出来,但是Optional的设计初衷并不是这样的,它的设计初衷仅仅是要支持能返回Optional的语法,由于它设计时就没有考虑将其作为类的字段使用,所以它也并未实现序列化接口,所以如果在框架或者序列化库中使用了 Optional修饰字段,那么可能会引发错误 但是如上我们看到了,Optional应用到bean中也是不错的,能够清楚的反映出那些字段是有可能为null的,并且可以使用Optional的特性,可以这样在bean中应用Optional public class Car { private Insurance insurance; public Optional<Insurance> getInsuranceAsOptional() { return Optional.ofNullable(insurance); } } 使用filter剔除特定的值 如果需要判断某个公司,那么我们需要这样的判断 Insurance insurance = ...; if (null != insurance && "lalala".equals(insurance.getName())){ System.out.println("..."); } 使用filter方法 Optional<Insurance> insurance = null; insurance.filter(i -> "lalala".equals(i.getName())) .ifPresent(i -> System.out.println("...")); 如上的ifPresent方法是判断i是否是空值,不是空值就执行后面的输出,是空即什么都不做 异常与Optional对象 String转换为Integer对象,如果转换错误就会爆数字格式化异常,我们必须try上异常以处理异常 需求:输入参数转换为int,然后返回该转换后的值,出错的话就返回0 public Integer StringParse(String str){ if (null == str) return 0; try { return Integer.parseInt(str); }catch (NumberFormatException e){ return 0; } } 用Optional解决 public Optional<Integer> StringParse(String str){ try { return Optional.of(Integer.parseInt(str)); }catch (NumberFormatException e){ return Optional.empty(); } } 避免使用基本类型的Optional对象 对于之前的函数式接口,我们提到的如果基本类型比较多,那么就优先使用对应的基本类型的函数式接口,比如IntFunction,但是Optional不推荐使用OptionalInt等类似的基本类型对象,因为这些对象中并没有map和filter等方法

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

JavaScript学习(十二)---正则表达式

目录 正则表达式基础 正则表达式的基本结构 正则表达式的作用 1.测试字符串的某个模式 2.替换文本 3.根据模式匹配从字符串中提取一个子字符串 正则表达式语法 模式匹配符 定义符与原义字符 (1)文本验证定位符 例子:匹配字符“^”的使用 匹配字符"$"的使用 用“\b”匹配一个自边界 限定符与选择匹配符 (1)限定符 (2)贪婪匹配与非贪婪匹配 (3)选择匹配符 实际应用 (1)普通字符匹配 (2)限制表单输入的内容 (3)去掉重复的字符 正则表达式基础 正则表达式描述了一种字符串匹配的模式,即可让用户通过使用一系列普通字符和特殊字符来构建能够明确描述文本字符串的匹配模式,可以用来检查一个字符串是否含有某种子字符串、将匹配的子字符串做替换或者从某个字符串中取出符合某个条件的子字符串等。 正则表达式的基本结构 一个正则表达式就是由普通字符(如字符a-z)以及特殊字符(称为元字符)组成的文字模式。 语法:/匹配对象的模式/ 其中,位于“/”定界符之间的部分就是将要在目标对象中进行匹配的模式。用户只要把希望查找匹配对象的模式内容放入“/”定界符之间即可。 例如:在字符串abcd中查找匹配模式bc。代码如下: /bc/ 正则表达式的作用 正则表达式是一种可以用于模式匹配和替换的强有力的工具。其作用如下: 1.测试字符串的某个模式 例如:可以对一个输入字符串进行测试,测试该字符串是否存在一个电话号码或一个信用卡号码模式,这称为数据有效性验证。 2.替换文本 可以在文档中使用一个正则表达式来标识特定文字,然后可以将其全部删除,或者替换为别的文字。 3.根据模式匹配从字符串中提取一个子字符串 可以在文本或输入字段中查找特定文字。 正则表达式语法 正则表达式的语法主要是对各个元字符功能的描述。元字符从功能上大致分为模式匹配符、定位符与原义字符、限定符、选择匹配符、特殊字符、字符匹配符、分组组合和反向引用符。 模式匹配符 定义符与原义字符 (1)文本验证定位符 定位符用于规定匹配模式在目标字符中出现的位置。例如,规定匹配模式只能出现在开头或结尾处,这样对文本格式的验证非常有用。 在正则表达式中,有以下几个用于验证文本的定义符。 用“^”匹配目标字符串的开始位置 匹配必须发生在目标字符串的开头处,“^”必须出现在表达式的最前面才具有定位符作用。 例子:匹配字符“^”的使用 <h3>行首匹配字符^的使用</h3> <script type="text/javascript" language="JavaScript"> var reg_expression=/^ming/; //使用行首元字符 var textstring="mingrisoft"; var result=reg_expression.test(textstring); //匹配时返回true,否则返回false document.write("<font size='+1'>"+result+"<br />"); if(result){ document.write("正则表达式/^ming/匹配字符串\""+textstring+"\".<br>"); }else{ alert("未找到匹配的模式!"); } </script> 匹配字符"$"的使用 <h3>行首匹配字符$的使用</h3> <script type="text/javascript" language="JavaScript"> var reg_expression=/ft$/; //使用行首元字符 var textstring="mingrisoft"; var result=reg_expression.test(textstring); //匹配时返回true,否则返回false document.write("<font size='+1'>"+result+"<br />"); if(result){ document.write("正则表达式/ft$/匹配字符串\""+textstring+"\".<br>"); }else{ alert("未找到匹配的模式!"); } </script> 用“\b”匹配一个自边界 “\b”包含了字与空格间的位置,以及目标字符串的开始和结束位置等。 <h3>行首匹配字符\b的使用</h3> <script type="text/javascript" language="JavaScript"> var reg_expression=/\bming\b/; //使用行首元字符 var textstring="ming risoft"; var result=reg_expression.test(textstring); //匹配时返回true,否则返回false document.write("<font size='+1'>"+result+"<br />"); if(result){ document.write("正则表达式//\b ming \b//匹配字符串\""+textstring+"\".<br>"); }else{ alert("未找到匹配的模式!"); } </script> 限定符与选择匹配符 (1)限定符 用“+”限定必须出现一次或连续多次。 例如:“/fo+/”,因为上述正则表达式中包含“+”元字符,表示可以与目标对象中的“fool”、“fo”或者“football”等字母“f”后面连续出现一个或多个字母“o”的字符串相匹配。 用“*”可以限定出现的次数。 用“?”限定最多出现一次。 用“{n}”限定连续出现的次数。 用“{n,}”限定至少出现的次数。 用“{n,m}”限定最少与最多出现的次数。 (2)贪婪匹配与非贪婪匹配 默认情况下,正则表达式使用最长匹配原则,即贪婪匹配原则。 (3)选择匹配符 选择匹配符“|”,用于选择匹配两个选项之中的任意一个,其两个选项是“|”字符两边尽可能最大的表达式 实际应用 (1)普通字符匹配 1.匹配中文字符的正则表达式: [\u4e00-\u9fa5] 2.匹配双字节字符(包括汉字在内): [^x00-xff] 3.匹配空行的正则表达式: n[s|]*r 4.匹配HTML标记的正则表达式: /<.*>.*</1>|<(.*)/>/ 5.匹配首尾空行的正则表达式: (^s*)|(s*$) 6.匹配网址URL的正则表达式: http://([w-]+.)+[w-]+(/[w-./?%&=]*)? 7.匹配E-mail地址的正则表达式: w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)* (2)限制表单输入的内容 在网页编程中,经常会用到限制网页表单中的文本框输入内容的情况。下面是一些利用正则表达式来实现这种功能的实例 1.用正则表达式限制只能输入中文: onkeyup="value=value.replace(/[^u4E00-u9FA5]/g,")" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,"))" 2.用正则表达式限制只能输入数字: onkeyup="value=value.replace(/[^d]/g,") "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,"))" 3.用正则表达式限制只能输入数字和英文: ​ onkeyup="value=value.replace(/[W]/g,") "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,"))" ​ 4.用正则表达式限制只能输入全角字符: ​ onkeyup="value=value.replace(/[^FF00-uFFFF]/g,") "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^FF00-uFFFF]/g,"))" ​ (3)去掉重复的字符 利用正则表达式可以去掉字符串中重复的字符。 <script type="text/javascript" language="JavaScript"> var s="asfasfafbssli"; var s1=s.replace(/(.).*\1/g,"$1"); var re=new RegExp("["+s1+"]","g"); var s2=s.replace(re,""); alert(s1+s2); </script>

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

Goalng下的反射模块reflect学习使用

反射reflection 反射 ●可以大大提高程序的灵活性,使得interface{}有更大的发挥余地 ●反射使用TypeOf和ValueOf函数从接口中获取目标对象信息 ●反射会将匿名字段作为独立字段(匿名字段的本质) ●想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface ●通过反射可以"动态" 调用方法 常用的类型、函数和方法 1//返回动态类型i的类型,如果i是一个空结构体类型,TypeOf将返回nil 2func TypeOf(i interface{})Type 3 4//Type 接口类型 5typeTypeinterface { 6 Align() int 7 FieldAlign() int 8//指定结构体中方法的下标,返回某个方法

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

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

用户登录
用户注册