1、 字符串操作——String类
1、 String可以表示一个字符串。
2、 String类实际是使用字符数组存储的。
String类的两种赋值方式:
- 一种称为直接赋值:String name = “小白”
- 通过关键字new调用String的构造方法赋值:String name = new String(“小白”)
String类的两种赋值分析:
- 字符串常量池
- String name = new String(“小白”), 在内存中的分析
- String name = “小白”, 在内存中的分析
String类编译期与运行期分析:
- 编译期和运行期
- 代码示例: 4种情况分析
package com.vince;
/**
*
* @author vince
* @description
* String 表示一个字符串,内部使用字符数组实现,不能被继承(最终类),不可变
*/
public class StringDemo {
public static void main(String[] args) {
//String 的两种赋值方式,JAVA推荐使用第一种方式
//1 直接赋值
String s1 = "你好"; //此时“你好”放在字符串常量池中
//2 使用new关键字创建对象,new:表示申请内存空间
////面试题 问以下代码创建了几个对象? 2个
String s2 = new String("你好");
String s3 = "你好"; //直接在常量池中寻找,省内存空间
System.out.println(s1==s2);//false
System.out.println(s1==s3);//true
System.out.println("-----------------");
//代码示例:4种情况分析:直接赋值字符串连接时,考虑编译期和运行期
//如果在编译期值 可以被确定,那么就使用已有的对象,否则会创建新的对象
String a = "a";
String a1 = a+1;
String a2 = "a1";
System.out.println(a1==a2);//false
final String b = "b"; //b此时是常量
String b1 = b+1; //在编译器b1可以被确定
String b2 = "b1";
System.out.println(b1==b2);//true
String c = getC();
String c1 = c+1;
String c2 = "c1";
System.out.println(c1==c2);//false
final String d = getD(); //方法在运行期才会获得结果
String d1 = d+1;
String d2 = "d1";
System.out.println(d1==d2);//false
}
private static String getC(){
return "c";
}
private static String getD(){
return "d";
}
}
(1)字符与字符串操作方法
(2)判断是否以指定内容开头或结尾
(3)替换操作
(4)字符串截取操作
(5)字符串拆分操作
(6)字符串查找操作
(7)其它操作方法
import java.util.Arrays;
public class StringDemo2 {
public static void main(String[] args) {
String str = " fkwefwfa d6737383 ";
char c = str.charAt(1);
System.out.println(c); //f
System.out.println(str.toCharArray()); // fkwefwfa d6737383
char[] cs = {'a','b','c'};
String s1 = new String(cs);
System.out.println(s1); //abc
String s2 = new String(cs,0,1);
System.out.println(s2); //a
System.out.println(Arrays.toString(str.getBytes()));
//[32, 102, 107, 119, 101, 102, 119, 102, 97, 32, 100, 54, 55, 51, 55, 51, 56, 51, 32]
System.out.println(str.replace('w', '*')); // fk*ef*fa d6737383
System.out.println(str.replaceAll("\\d", "*")); // fkwefwfa d*******
System.out.println(str.substring(0, 4)); //fkw
System.out.println(Arrays.toString(str.split("d"))); //[ fkwefwfa , 6737383 ]
System.out.println(str.contains("a")); //true
System.out.println(str.indexOf("f")); //1
System.out.println(str.lastIndexOf("f")); //7
System.out.println(str.isEmpty()); //false
System.out.println(str.length()); //19
System.out.println(str.trim()); //fkwefwfa d6737383
System.out.println(str.concat("*****")); // fkwefwfa d6737383 *****
System.out.println(String.valueOf(10)); //10
}
}
2、字符串操作——StringBuffer类
在实际开发当中, 我们经常会使用到字符串连接的操作, 如果用String来操作, 则使用“ +” 号完成字符串的连接操作。
使用String连接字符串, 代码性能会非常低, 因为String的内容不可改变。
解决这个问题的方法是使用StringBuffer。
StringBuffer常用操作方法
public class StringBufferDemo {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = a+b+1; //会出现5个对象
System.out.println(c);
String d = "a"+1+2+3+4+"b";//a1234b //常量相加没有性能问题(编译期进行优化)
//StringBuffer目的是来解决字符串相加时带来的性能问题(常量与变量)
//StringBuffer的内部实现采用字符数组,默认数组的长度为16,超过数组大小时,动态扩充的算法是原来长度*2+2
//所以当我们预知要添加的数据长度时,建议使用带初始化容量的构造方法,来避免动态扩充的次数,从而提高效率
//带线程锁,故线程安全的,但会影响性能,
StringBuffer sb = new StringBuffer(32);//带容量的构造(建议)
sb.append(a).append(b).append(1);
System.out.println(sb.toString());
StringBuffer sb2 = new StringBuffer("abc");
sb2.delete(0, 1);
System.out.println(sb2); //bc
}
}
3、字符串操作——StringBuilder类
StringBuffer的兄弟StringBuilder:
一个可变的字符序列。 此类提供一个与 StringBuffer 兼容的 API, 但不保证同步。 该类被设计用作 StringBuffer 的一个简易替换, 用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
如果可能, 建议优先采用该类, 因为在大多数实现中, 它比StringBuffer 要快。
JDK1.5以后, 字符串相加原理分析
public class StringBuilderDemo {
public static void main(String[] args) {
//面试题 :StringBuffer与StringBuilder的区别?
//StringBuffer是线程安全的,性能低,适合在多线程的使用,JDK1.0
//StringBuilder是线程不安全的,性能高,适合在单线程中使用,这种情况占多大数,在jdk1.5后添加
//StringBuilder sb = new StringBuilder();
//字符串相加操作
//1、多个常量相加没有性能问题 ,在编译期优化
//2、变量与常量相加,会产生多个垃圾对象
//String a = "a"+1;
//String b = a+"b";
String c = null;
for(int i=0;i<5;i++){
c+=i; //每次循环会产生一个StringBuilder对象实现拼接,性能低,最好是手动创建StringBuilder来拼接
}
//1、字符串相加,在编译后,会使用StringBuilder来优化代码,实现拼接
}
StringBuilder sb3=new StringBuilder();
sb3.append(1).append(2).append(3);
System.out.println(sb3);
}
4、程序国际化
(1) 对国际化程序的理解
Internationalization: 国际化程序可以这样理解:
同一套程序代码可以在各个语言环境下进行使用。
各个语言环境下, 只是语言显示的不同, 那么具体的程序操作本身都是一样的, 那么国际化程序完成的就是这样的一个功能。
(2)Locale类
Locale 对象表示了特定的地理、 政治和文化地区。 需要 Locale 来执行其任务的操作称为语言环境敏感的操作, 它使用 Locale 为用户量身定制信息。 例如, 显示一个数值就是语言环境敏感的操作, 应该根据用户的国家、 地区或文化的风俗/传统来格式化该数值。
使用此类中的构造方法来创建 Locale:
Locale(String language)
Locale(String language, String country)
通过静态方法创建Locale:
getDefault()
(3)ResourceBundle类
国际化的实现核心在于显示的语言上, 通常的做法是将其定义成若干个属性文件(文件后缀是*.properties) , 属性文件中的格式采用“ key=value” 的格式进行操作。
ResourceBundle类表示的是一个资源文件的读取操作, 所有的资源文件需要使用ResourceBundle进行读取, 读取的时候不需要加上文件的后缀。
getBundle(String baseName)
getBundle(String baseName,Locale locale)
getString(String key)
(4)处理动态文本
前面的示例读取的内容都是固定的, 如果现在假设要想打印这样的信息“ 欢迎你,XXX! ” , 具体的名字不是固定的, 那么就要使用动态文本进行程序的处理。
进行动态的文本处理, 必须使用java.text.MessageFormat类完成。 这个类是java.text.Format的子类。
package com.vince;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Scanner;
/**
* 程序国际化
* 1、Locale
* 2、Properties文件:属性文件(配置文件),内容以键值对的形式存放(key-value)
* 3、ResourceBundle工具类,来绑定属性文件,并指定Locale对象,来自动选择使用哪个属性文件,默认将使用与操作系统相同的语言环境。
* getString()方法来从属性文件中使用key来获取value
* 注意,ResourceBundle工具类是只读的
*/
public class I18NDemo {
public static void main(String[] args) {
//创建一个本地语言环境对象,该对象会根据参数设置来自动选择与之相关的语言环境
//参数:语言,地区
Locale locale_CN = new Locale("zh","CN");
Locale locale_US = new Locale("en","US");
//获取当前系统默认的语言环境
Locale locale_default = Locale.getDefault();
Scanner input = new Scanner(System.in);
//用于绑定属性文件的工具类(参数:属性文件的基本名(就是前缀,比如,info))
//ResourceBundle 工具类
ResourceBundle r = ResourceBundle.getBundle("com.vince.info",locale_CN);
// ResourceBundle r = ResourceBundle.getBundle("com.vince.info",locale_US);
System.out.println(r.getString("system.name"));
System.out.println(r.getString("input.username"));
String username = input.nextLine();
System.out.println(r.getString("input.password"));
String password = input.nextLine();
if("admin".equals(username) && "123".equals(password)){
System.out.println(r.getString("login.success"));
String welcome = r.getString("welcome");
//动态文本格式化
welcome = MessageFormat.format(welcome, username);
System.out.println(welcome);
}else {
System.out.println(r.getString("login.error"));
}
}
}
/*
员工管理系统
输入用户名:
admin
输入密码:
123
登录成功
欢迎你,admin
EMP Manager System
Input UserName:
admin
Input Password:
123
Login Success!
welcome,admin
*/
info_zh_CN.properties
system.name=\u5458\u5DE5\u7BA1\u7406\u7CFB\u7EDF
input.username=\u8F93\u5165\u7528\u6237\u540D\uFF1A
input.password=\u8F93\u5165\u5BC6\u7801\uFF1A
login.success=\u767B\u5F55\u6210\u529F
login.error=\u767B\u5F55\u9519\u8BEF
welcome=\u6B22\u8FCE\u4F60\uFF0C{0}
info_en_US.properties
system.name=EMP Manager System
input.username=Input UserName:
input.password=Input Password:
login.success=Login Success!
login.error=Login Error
welcome=welcome,{0}
5、Math与Random类
(1)Math类
Math 类包含用于执行基本数学运算的方法, 如初等指数、 对数、 平方根和三角函数。
使用Math类可以有两种方式:
- 直接使用(Math所在的包java.lang为默认引入的包)
- 使用 import static java.lang.Math.abs; 静态导入
(2)Random类
Random: 此类的实例用于生成伪随机数流
import static java.lang.Math.floor; //静态导入
import java.util.Random;
public class MathRandomDemo {
public static void main(String[] args) {
System.out.println(Math.PI);
System.out.println(Math.abs(-10));
System.out.println(Math.round(Math.random()*1000)/1000.0); //应用random以及round取三位小数
System.out.println(Math.sqrt(2));
System.out.println(floor(1.234564));
Random r = new Random();
System.out.println(r.nextLong());
System.out.println(r.nextInt(10));
}
}
/*
3.141592653589793
10
0.461
1.4142135623730951
1.0
3352128650373644561
7
*/
6、日期操作类
(1)Date类
类 Date 表示特定的瞬间, 精确到毫秒, 也就是程序运行时的当前时间。
Date date = new Date(); // 实例化Date对象, 表示当前时间
(2)Calendar类
Calendar, 日历类, 使用此类可以将时间精确到毫秒显示。
//两种实例化方式
Calendar c = Calendar.getInstance();
Calendar c = new GregorianCalendar();
(3)DateFormat类及子类SimpleDateFormat
package com.vince;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class DateDemo {
public static void main(String[] args) {
Date date = new Date();
// java.sql.Date sqlDate = new java.sql.Date();
System.out.println(date);
// 使用两个构造方法
// Date(long date) 参数是毫秒
// Date()
Calendar c1 = Calendar.getInstance();
Calendar c2 = new GregorianCalendar();
int year = c1.get(Calendar.YEAR);
int month = c1.get(Calendar.MONTH);
int day = c1.get(Calendar.DAY_OF_MONTH);
int hour = c1.get(Calendar.HOUR_OF_DAY);
int minute = c1.get(Calendar.MINUTE);
int second = c1.get(Calendar.SECOND);
int millisecond = c1.get(Calendar.MILLISECOND);
StringBuilder sb = new StringBuilder(50);
sb.append(year).append("年").append(month).append("月").append(day).append("日").append(hour).append(":")
.append(minute).append(":").append(second).append(" ").append(millisecond);
System.out.println(sb.toString());
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
String nowDate = df.format(new Date());
System.out.println(nowDate);
}
}
/*
Sat Oct 16 23:29:20 CST 2021
2021年9月16日23:29:20 147
2021年10月16日 23:29:20 179
*/
7、对象比较器Arrays.sort()
对两个或多个数据项进行比较, 以确定它们是否相等, 或确定它们之间的大小关系及排列顺序称为比较。
前面我学习过Arrays.sort方法可实现对象的排序操作:
public static void sort(Object[] a)
(1) Comparable接口:
此接口强行对实现它的每个类的对象进行整体排序。 这种排序被称为类的自然排序, 类的compareTo 方法被称为它的自然比较方法。
(2) Comparator接口:
Comparable接口是要求自定义类去实现, 按照OO原则: 对修改关闭, 对扩展开放。那么如果这个类已经定义好了, 不想再去修改它, 那如何实现比较呢?
Comparator接口: 强行对某个对象collection进行整体排序的比较
Test
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] nums = {34,54,22,3,5,6,7,87,9};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums)); //[3, 5, 6, 7, 9, 22, 34, 54, 87]
String[] names = {"jack","tom","菲菲","你好"};
Arrays.sort(names);
System.out.println(Arrays.toString(names)); //[jack, tom, 你好, 菲菲]
Cat[] cats = {new Cat("愤愤",1),new Cat("菲菲",4),new Cat("Tom",2)};
Arrays.sort(cats);
System.out.println(Arrays.toString(cats));
//[Cat [name=愤愤, age=1], Cat [name=Tom, age=2], Cat [name=菲菲, age=4]]
Dog[] dogs = {new Dog("愤愤",1),new Dog("菲菲",4),new Dog("Tom",2)};
Arrays.sort(dogs,new DogComparator());
System.out.println(Arrays.toString(dogs));
//[Dog [name=愤愤, age=1], Dog [name=Tom, age=2], Dog [name=菲菲, age=4]]
}
}
Cat
/**
* 自定义对象,要实现比较排序
* 1、可以实现Comparable的comparaTo方法
* @author vince
* @description
*/
public class Cat implements Comparable<Cat>{
private String name;
private int age;
public Cat() {
super();
}
public Cat(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Cat [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Cat o) {
// if(this.age<o.age)return -1;
// if(this.age>o.age)return 1;
// return 0;
return this.age-o.age;
}
}
Dog
public class Dog {
private String name;
private int age;
@Override
public String toString() {
return "Dog [name=" + name + ", age=" + age + "]";
}
public Dog(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Dog() {
super();
}
}
DogComparator
import java.util.Comparator;
public class DogComparator implements Comparator<Dog>{
@Override
public int compare(Dog o1, Dog o2) {
return o1.getAge()-o2.getAge();
}
}
8、对象的克隆
将一个对象复制一份, 称为对象的克隆技术。
在Object类中存在一个clone()方法:
protected Object clone() throws CloneNotSupportedException
如果某个类的对象要想被克隆, 则对象所在的类必须实现Cloneable接口。 此接口没有定义任何方法, 是一个标记接口
Cat
/**
* 对象需要具备克隆功能:
* 1、实现Cloneable接口,(标记接口)
* 2、重写Object类中的clone方法
* @author vince
* @description
*/
public class Cat implements Cloneable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Cat(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Cat() {
super();
}
//重写Object中的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Cat [name=" + name + ", age=" + age + "]";
}
}
Test
package com.vince;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("喵喵小白",2);
try {
Cat newCat = (Cat) cat.clone();
System.out.println("cat="+cat);
//cat=Cat [name=喵喵小白, age=2]
System.out.println("new cat="+newCat);
//new cat=Cat [name=喵喵小白, age=2]
System.out.println(cat==newCat);
//false
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
9、System与 Runtime类
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。 该类位于java.lang包。
(1)成员变量
System类内部包含in、out和err三个成员变量, 分别代表标准输入流(键盘输入), 标准输出流(显示器)和标准错误输出流。
(2)成员方法
System类中提供了一些系统级的操作方法
- public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
该方法的作用是数组拷贝, 也就是将一个数组中的内容复制到另外一个数组中的指定位置, 由于该方法是native方法, 所以性能上比使用循环高效。 - public static long currentTimeMillis()
该方法的作用是返回当前的计算机时间, 时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数 - public static void exit(int status)
该方法的作用是退出程序。 其中status的值为0代表正常退出, 非零代表异常退出。 使用该方法可以在图形界面编程中实现程序的退出功能等。 - public static void gc()
该方法的作用是请求系统进行垃圾回收。 至于系统是否立刻回收, 则取决于系统中垃圾回收算法的实现以及系统执行时的情况。 - public static String getProperty(String key)
该方法的作用是获得系统中属性名为key的属性对应的值。
java.version Java 运行时环境版本
java.home Java 安装目录
os.name 操作系统的名称
os.version 操作系统的版本
user.name 用户的账户名称
user.home 用户的主目录
user.dir 用户的当前工作目录
Runtime类: 每个 Java 应用程序都有一个 Runtime 类实例, 使应用程序能够与其运行的环境相连接。
//获取Java运行时相关的运行时对象
Runtime rt = Runtime.getRuntime();
System.out.println("处理器数量: " + rt.availableProcessors()+" 个");
System.out.println("Jvm总内存数 : "+ rt.totalMemory()+" byte");
System.out.println("Jvm空闲内存数: "+ rt.freeMemory()+" byte");
System.out.println("Jvm可用最大内存数: "+ rt.maxMemory()+" byte");
//在单独的进程中执行指定的字符串命令。
rt.exec("notepad");
package com.vince;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class SystemRuntimeDemo {
public static void main(String[] args) {
System.out.println("向控制台输出");
System.err.println("出错啦");
int[] num1 = {1,2,3,4,5,6,7,8};
int[] num2 = new int[num1.length];
//参数(源数组,源数组的起始位置 ,目标数组,目标数组的起始位置 ,长度)
System.arraycopy(num1, 0, num2, 0, num1.length);
System.out.println(Arrays.toString(num2));
System.out.println(System.currentTimeMillis());
Date nowDate = new Date(System.currentTimeMillis());
DateFormat df = new SimpleDateFormat("HH:mm:ss");
String now = df.format(nowDate);
System.out.println(now);
//退出JVM
//System.exit(0);
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("java.home"));
System.out.println(System.getProperty("os.name"));
Runtime rt = Runtime.getRuntime();
System.out.println("处理器数量:" + rt.availableProcessors()+" 个");
System.out.println("Jvm总内存数 :"+ rt.totalMemory()+" byte");
System.out.println("Jvm空闲内存数: "+ rt.freeMemory()+" byte");
System.out.println("Jvm可用最大内存数: "+ rt.maxMemory()+" byte");
//在单独的进程中执行指定的字符串命令。
try {
rt.exec("notepad"); //打开记笔本
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//加载C、C++编写的类库
//System.loadLibrary(libname)
}
}
10、 数字处理工具类
(1)BigInteger
可以让超过Integer范围内的数据进行运算。
构造方法: public BigInteger(String val)
常用方法:
public BigInteger add(BigInteger val)
public BigInteger subtract(BigInteger val)
public BigInteger multiply(BigInteger val)
public BigInteger divide(BigInteger val)
public BigInteger[] divideAndRemainder(BigInteger val)
(2)BigDecimal
由于在运算的时候, float类型和double很容易丢失精度, 为了能精确的表示、 计算浮点数, Java提供了BigDecimal,不可变的、 任意精度的有符号十进制数。
构造方法: public BigDecimal(String val)
常用方法:
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor)
(3)DecimalFormat:
Java 提供 DecimalFormat类, 帮你用最快的速度将数字格式化为你需要的样子。
例如, 取2位小数。
示例:
double pi=3.1415927; //圆周率
//取一位整数, 结果: 3
System.out.println(new DecimalFormat("0").format(pi));
//取一位整数和两位小数, 结果3.14
System.out.println(new DecimalFormat("0.00").format(pi));
//取两位整数和三位小数, 整数不足部分以0填补, 结果: 03.142
System.out.println(new DecimalFormat("00.000").format(pi));
//取所有整数部分, 结果: 3
System.out.println(new DecimalFormat("#").format(pi));
//以百分比方式计数, 并取两位小数, 结果: 314.16%
System.out.println(new DecimalFormat("#.##%").format(pi));
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
//大整数运算
String val1 = "84567890986544567";
String val2 = "45097659985495567";
BigInteger b1 = new BigInteger(val1);
BigInteger b2 = new BigInteger(val2);
System.out.println(b1.add(b2));//+
System.out.println(b1.subtract(b2));//-
System.out.println(b1.multiply(b2));//*
System.out.println(b1.divide(b2));// /
System.out.println(b1.remainder(b2));// %
System.out.println(Arrays.toString(b1.divideAndRemainder(b2))); // / and %
String val3 = "5696.698494847898754789";
String val4 = "6";
BigDecimal b3 = new BigDecimal(val3);
BigDecimal b4 = new BigDecimal(val4);
System.out.println(b3.add(b4));
System.out.println(b3.subtract(b4));
System.out.println(b3.multiply(b4));
System.out.println(b3.divide(b4));
//System.out.println(b3.scale()-b4.scale());
double pi=3.1415927;//圆周率
//取一位整数,结果:3
System.out.println(new DecimalFormat("0").format(pi));
//取一位整数和两位小数,结果3.14
System.out.println(new DecimalFormat("0.00").format(pi));
//取两位整数和三位小数,整数不足部分以0填补,结果:03.142
System.out.println(new DecimalFormat("00.000").format(pi));
//取所有整数部分,结果:3
System.out.println(new DecimalFormat("#").format(pi));
//以百分比方式计数,并取两位小数,结果:314.16%
System.out.println(new DecimalFormat("#.##%").format(pi));
long num = 635463773;
System.out.println(new DecimalFormat("###,###").format(num));
}
}
/*
129665550972040134
39470231001049000
3813813993401642148647580426434489
1
39470231001049000
[1, 39470231001049000]
5702.698494847898754789
5690.698494847898754789
34180.190969087392528734
949.4497491413164591315
3
3.14
03.142
3
314.16%
635,463,773
*/
11、 MD5工具类
MD5的全称是Message-Digest Algorithm 5(信息-摘要算法)
//确定计算方法
MessageDigest md5=MessageDigest.getInstance("MD5");
//JDK1.8新增Base64
String newstr = Base64.getEncoder().encodeToString(md5.digest(str.getBytes("utf-8")));
//1.8之前使用sun.misc.BASE64Encoder(此类没有访问权限, 在rt.jar中添加访问权限: sun/misc/*)
BASE64Encoder base64 = new BASE64Encoder();
base64.encode(md5.digest(str.getBytes("utf-8")));
package com.vince;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class MD5Demo {
private static String savePassword = "pmq7VoTEWWLYh1ZPCDRujQ==";//存储的密文
public static void main(String[] args) {
test();
System.out.println(login("admin123456"));
}
private static boolean login(String password){
if(savePassword.equals(md5(password))){
return true;
}else{
return false;
}
}
//计算MD5的工具方法
private static String md5(String password){
try {
MessageDigest md = MessageDigest.getInstance("md5");
//通过MD5计算摘要
byte[] bytes = md.digest(password.getBytes("UTF-8"));
String str = Base64.getEncoder().encodeToString(bytes);
return str;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
private static void test() {
String password = "admin123456"; //dsfkjdskfj76776f98732 明文(原文)
String savePassword = "pmq7VoTEWWLYh1ZPCDRujQ==";//存储的密文
try {
MessageDigest md = MessageDigest.getInstance("md5");
//通过MD5计算摘要
byte[] bytes = md.digest(password.getBytes("UTF-8"));
System.out.println(Arrays.toString(bytes));
String mdStr = new String(bytes);
//System.out.println(mdStr);
//a-z A-Z 0-9 / * BASE64编码算法
// 1.8版本
String str = Base64.getEncoder().encodeToString(bytes);
System.out.println(str);
//JDK1.8之前使用
// BASE64Encoder base64 = new BASE64Encoder();
// String str = base64.encode(bytes);
//base64解码
BASE64Decoder decoder = new BASE64Decoder();
byte[] bs = decoder.decodeBuffer(str);
System.out.println(Arrays.toString(bs));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
[-90, 106, -69, 86, -124, -60, 89, 98, -40, -121, 86, 79, 8, 52, 110, -115]
pmq7VoTEWWLYh1ZPCDRujQ==
[-90, 106, -69, 86, -124, -60, 89, 98, -40, -121, 86, 79, 8, 52, 110, -115]
true
*/
12、Lambda表达式
(1)Lambda表达式
Lambda表达式(也称为闭包) 是整个Java 8发行版中最受期待的在Java语言层面上的改变, Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据。
Lambda表达式用于简化JAVA中接口式的匿名内部类。 被称为函数式接口的概念。 函数式接口就是一个具有一个方法的普通接口。 像这样的接口, 可以被隐式转换为lambda表达式。
语法:
(参数1,参数2…) -> { … }
- 没有参数时使用Lambda表达式
- 带参数时使用Lambda表达式
- 代码块中只一句代码时使用Lambda表达式
- 代码块中有多句代码时使用Lambda表达式
- 有返回值的代码块
- 参数中使用final关键字
(2)接口中的默认方法和静态方法
interface A{
public default void print(){}
public static void method(){}
}
默认方法与静态方法并不影响函数式接口的契约, 可以任意使用
package com.vince;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaDemo {
public static void main(String[] args) {
// IEat ieat = new IEatImpl();
// ieat.eat();
// IEat ieat2 = new IEat(){
// public void eat(){
// System.out.println("eat banana");
// }
// };
// ieat2.eat();
//lambda表达式:
//好处:1代码更简洁,2,不会单独生成class文件
// IEat ieat3 = ()->{System.out.println("eat apple banana");};
//没有参数时使用
// IEat ieat3 = ()-> System.out.println("eat apple banana");
// ieat3.eat();
//带参数时使用,参数的类型可以省略
// IEat ieat3 = (thing,name) -> System.out.println("eat..."+thing+"..."+name);
// ieat3.eat("apple","大冰");
//带参数时使用,参数的类型可以省略,代码块中有多行代码
// IEat ieat3 = (thing,name) -> {
// System.out.println("eat..."+thing);
// System.out.println(name);
// };
// ieat3.eat("apple","大冰");
//带返回值的方法
// IEat ieat3 = (thing,name)->{
// System.out.println(name+ " eat "+thing);
// return 10;
// };
//带返回值 的方法中只有一句实现代码
IEat ieat3 = (final String thing,final String name)-> thing==null?1:0;
ieat3.eat("apple", "大冰");
Student[] students = {
new Student("张三",18),
new Student("张四",28),
new Student("张一",15)};
// Arrays.sort(students,new Comparator<Student>() {
// public int compare(Student o1, Student o2) {
// return o1.getAge()-o2.getAge();
// };
// });
// Comparator<Student> c = (o1,o2)->o1.getAge()-o2.getAge();
Arrays.sort(students,(o1,o2)-> o1.getAge()-o2.getAge());
System.out.println(Arrays.toString(students));
IEat.method();
}
}
//只有一个抽象方法的接口
interface IEat{
public int eat(final String thing,final String name);
public default void print(){
System.out.println("print test");
}
public static void method(){
System.out.println("static method..");
}
}
//class IEatImpl implements IEat{
// public void eat(String thing){
// System.out.println("eat--"+thing);
// }
//}
package com.vince;
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
}