1、Scanner
Scanner是一个基于正则表达式的文本扫描器,它可以从字符串、输入流、文件中解析出字符串或基本类型值。使用Scanner来获得用户输入会很方便,比如如果使用System.in.read()获得的是用户输入的字符编码值,而使用Scanner可以直接将用户的输入转化为需要的字符串或int等类型。下面为使用Scanner获得用户输入并打印用户输入的例子,用户输入一个int数值后再键入换行就会获得用户输入的int值并输出,如果输入的是0的话退出,如果用户输入的不是数字而是字母的话nextInt()会抛出java.util.InputMismatchException异常:
package xu;
public class Main {
public static void main(String[] args){
java.util.Scanner sc = new java.util.Scanner(System.in); //设置键盘输入为数据源
sc.useDelimiter("\n"); //设置用户输入的分隔符为换行,默认是空格、Tab、换行
int n = 0;
do{
n = sc.nextInt(); //nextFloat()为获得用户输入的float数值,next()为获得用户输入的字符串
System.out.println(n);
}while(n != 0);
}
}
2、System
System类表示当前Java程序的运行平台:
package xu;
import java.util.*;
import java.io.FileOutputStream;
public class Test
{
public static void main (String[] args)throws Exception
{
Map env = System.getenv(); //获得系统所有的环境变量
for(String name:env.keySet())
{
//System.out.println(name + ":" + env.get(name));
}
System.out.println(System.getenv("JAVA_HOME")); //获取指定的环境变量
Properties props = System.getProperties(); //获取所有的系统属性
props.store(new FileOutputStream("props.txt"), "System Properties"); //将属性写入都props.txt文件
System.out.println(System.getProperty("os.name")); //输出系统版本
long times = System.currentTimeMillis(); //获得到1970年的毫秒数(时间粒度与系统相关)
times = System.nanoTime(); //获得到1970年的纳秒数(时间粒度与系统相关)
String str1 = new String("Test");
String str2 = new String("Test");
System.out.println(str1.hashCode() == str2.hashCode()); //输出为true,hashCode()以序列内容计算HashCode
System.out.println(System.identityHashCode(str1) == System.identityHashCode(str2)); //输出为false,identityHashCode()以对象地址计算HashCode,能唯一的标识该对象
str1 = "Test";
str2 = "Test";
System.out.println(System.identityHashCode(str1) == System.identityHashCode(str2)); //输出为true
}
}
3、Runtime
Runtime类代表java程序的运行时环境,可以通过它访问JVM的相关信息,如处理器数量,内存信息等,它还可以通过exec()方法来启动一个进程或执行操作系统命令。每个java程序都有一个与之对应的Runtime实例,在程序中可以通过getRuntime()获得对应的Runtime对象。
package xu;
public class Test
{
public static void main (String[] args) throws Exception
{
Runtime rt = Runtime.getRuntime();
rt.availableProcessors(); //处理器数量
rt.totalMemory(); //总内存
rt.maxMemory(); //最大可用内存
rt.freeMemory(); //空闲内存
rt.exec("notepad.exe"); //运行记事本程序
}
}
与System类似,Runtime类也提供gc()、runFinalization()方法来通知系统进行垃圾回收、清理系统资源,并提供了load()、loadLibrary()来加载文件和动态链接库。
4、调用c/c++的动态链接库
native用来修饰一个方法,该方法在其他语言(c/c++)实现的文件中,具体为:
①、在java程序中用native修饰声明的方法,该方法只有签名,没有实现,编译该java程序,生成class文件。
②、用javah编译生成的class文件,会生成.h文件。
③、在cpp文件中实现方法,这时需要包含上面的.h文件(这个.h文件中又包含了jdk带的jni.h文件)。
④、将cpp文件编译成动态库
⑤、在java中使用System类的loadLibrary...()方法或Runtime类的loadLibrary...()方法加载动态库,然后就可以使用这个native方法了。
5、String、StringBuffer、StringBuilder
String:不能改变其中的内容。 对于String的改变不会影响到原对象,因为这些操作实际上都是生成新的String对象,所以如果对于String对象会进行大量修改操作的话不推荐使用
StringBuffer:可以通过append()、insert()等成员方法改变当前字符串序列内容。通过toString()来生成String,使用String的contentEquals()方法来判断String与StringBuffer的序列内容是否相同。
StringBuilder:StringBuffer的非线程安全版本,性能略高。
字符串连接最方便和直接的方式是通过"+"符号来实现,但是这种方式达到目的的效率比较低,且每执行一次都会创建一个String对象,即耗时,又浪费空间。使用StringBuilder类就可以避免这种问题的发生。
字符串连接:
String str = String.join(", ", "c++", "java", "c#"); //"c++, java, c#"
List list = List.of("c++", "java", "c#");
String s = String.join(", ", list); //"c++, java, c#"
StringBuilder strB = new StringBuilder("000");
StringBuilder strB2 = strB.append("123").append("abc").append('?');
System.out.println(strB2); //"000123abc?"
System.out.println(strB == strB2); //true
数值与String之间的互转:
/*****String转数值*****/
String s = "100";
Integer inte = Integer.valueOf(s); //String转Integer
int i = Integer.parseInt(s); // String转int
Float f1 = Float.valueOf("3.14"); //String转Float
float f2 = Float.parseFloat("3.14"); //String转float
/*****数值转String*****/
double d = 3.126;
String s3 = String.valueOf(d); //double转String
Double f = 12.345;
String s2 = f.toString(); //Double转String
String s4 = String.format("%.2f", d); //double转String,指定小数位数,四舍五入(如果要求不四舍五入而是直接舍去的话可以指定小数位数多一位,转换为String后再去掉最后的字符)
//int转String
String s7 = "" + 100; // "100"
String s9 = String.valueOf(100); // "100"
String s5 = "100";
String s6 = s5 + 200; // "100200"
//Integer转String
Integer n = 100;
String s8 = n.toString();
// 将byte[]转换为十六进制格式的hex string:
private String toHexString(byte[] digest) {
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
6、Math
Math提供了大量的数学计算类方法:
Math.pow(10); //乘方
Math.abs(-10); //绝对值
Math.max(10, 1); //最大值
double d = Math.floor(10.7); //10.0,往负方向的舍入,即取小于目标数的最大数
d = Math.floor(-10.1); // -11.0
d = Math.ceil(10.1); //11.0,往正方向的舍入,即取大于目标数的最小数
d = Math.ceil(-10.7); //-10.0
//Math.round():返回一个最接近浮点型参数值的整形,如果上下距离一样的话取最大的那个,即四舍五入取最大
long l = Math.round(12.4); //l为12
l = Math.round(-12.6); //l为-13
l = Math.round(12.5); //l为13
l = Math.round(-12.5); //l为-12
//Math.random():生成大于等于0.0且小于1.0的伪随机double值
double a = Math.random() * 10; //生成一个范围为[0,10)的随机double变量
a = Math.random() * 10 + 1; //生成一个范围为[1, 11)的随机double变量
7、Random和ThreadLocalRandom
Random用于生成伪随机数,它的默认构造函数使用当前时间作为种子,另一个构造函数需要一个long型参数作为种子,如果两个Random对象使用相同的种子,且生成随机数的函数顺序也相同,那么二者生成的随机数会一样。ThreadLocalRandom是Random的增强版,它使用静态方法current()来获取对应对象,拥有更好的线程安全。
package xu;
import java.util.concurrent.ThreadLocalRandom;
public class Test
{
public static void main(String[] args)
{
ThreadLocalRandom rand = ThreadLocalRandom.current();
rand.nextBoolean(); //boolean类型随机数
rand.nextDouble(); //double类型
System.out.println(rand.nextInt(0, 1)); //int类型,范围为[0,100)
}
}
8、BigInteger
long类型支持范围为-9223372036854775808 - 9223372036854775807,BigInteger支持更大的范围:
import java.math.BigInteger;
import java.util.regex.*;
public class Main {
public static void main(String[] args)
{
BigInteger n = new BigInteger("100");
n = n.add(new BigInteger("1")).subtract(BigInteger.ONE).multiply(BigInteger.TEN).divide(BigInteger.TWO);
System.out.println(n); // 500
n.mod(BigInteger.TWO); //求余
n.divideAndRemainder(BigInteger.TWO); //求商和求余,返回一个长度为2的BigInteger数组,0处为商,1处为余
long l = 100;
n = BigInteger.valueOf(l); //long转换为BigInteger
l = n.longValue(); //BigInteger转为long
l = n.longValueExact(); //BigInteger转为long,转换丢失精度的话会抛出ArithmeticException异常
}
}
9、BigDecimal
由于有的浮点数是不准确有误差的,所以使用==判断两个浮点数相等或者浮点数相加都会有问题,在java中可以使用BigDecimal类来解决这些问题。比较两个BigDecimal是否值相等,最好使用compareTo(),不要用equals(),因为1.2和1.20因为scale不同会导致equals()返回false。BigDecimal类的初始化和使用类似BigInteger:
import java.math.BigDecimal;
import java.math.BigInteger;
public class Main {
public static void main(String[] args)
{
BigDecimal b1 = new BigDecimal("3.14");
BigDecimal b2 = BigDecimal.valueOf(3.14);
boolean b = b1.equals(b2); //true
BigDecimal b3 = new BigDecimal(BigInteger.valueOf(314), 2/*小数点左移两位*/); // 3.14
b = b3.equals(b1); //true
BigDecimal b4 = new BigDecimal(BigInteger.valueOf(314), -2/*小数点又移两位*/); // 3.14E+4(31400.0)
}
}
BigDecimal也有类似Math的round()、floor()、ceil()方法,而且还可以指定保留的小树位数:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
public class Main {
public static void main(String[] args)
{
BigDecimal n = new BigDecimal(BigInteger.valueOf(546), 2); //5.46
BigDecimal n2 = n.setScale(0, RoundingMode.HALF_UP); //5, 相当于Math.round()
n2 = n.setScale(0, RoundingMode.CEILING); //6,相当于Math.ceil()
n2 = n.setScale(0, RoundingMode.FLOOR); //5,相当于Math.floor()
n2 = n.setScale(1, RoundingMode.HALF_UP); //5.5,第一个参数可以指定保留的小数位数
n2 = n.setScale(0, RoundingMode.UP); //6,取远离0的方向,如果n为-5.46的话n2为-6
n2 = n.setScale(0, RoundingMode.DOWN); //5,取接近0的方向,如果n为-5.46的话n2为-5
n2 = n.setScale(0, RoundingMode.HALF_DOWN); //取最接近的数字方向,与HALF_UP不同的是如果两边距离相同的话取最小的,四舍五入取最小
n2 = n.setScale(0, RoundingMode.HALF_EVEN); //取最接近的数字方向,与HALF_UP不同的是如果两边距离相同的话取最接近的偶数,即四舍五入取偶数
}
}
可以使用MathContenxt来指定BigDecimal使用的最大精度(从最左边不是0的数字开始,直到最右边使用的数字个数)和舍入方式,BigDecimal的precision()可以获得当前使用的精度:
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.math.MathContext;
public class Main {
public static void main(String[] args)
{
BigDecimal n = new BigDecimal("0.001236", new MathContext(2/*精度*/, RoundingMode.HALF_UP/*舍入方式*/)); //0.0012
int pre = n.precision(); //2
n = new BigDecimal("0.001236", new MathContext(3, RoundingMode.HALF_UP)); //0.00124
pre = n.precision(); //3
n = new BigDecimal("0.00004216");
pre = n.precision(); //4
}
}
下面提供了一个工具类Arith,它提供了对浮点型精确的加减乘除运算:
package xu;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class DecimalArith
{
private static final int DEF_DIV_SCALE = 10; //除法除不尽时精确到10位小数
private DecimalArith(){}
public static double add(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}
public static double sub(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.subtract(b2).doubleValue();
}
public static double mul(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).doubleValue();
}
public static double div(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.divide(b2, DEF_DIV_SCALE, RoundingMode.HALF_DOWN).doubleValue();
}
}
10、Timer
Java中的Timer执行的任务是在另一个线程中执行的:
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
public class Test
{
public static void main(String[] args)
throws Exception
{
Timer t = new Timer(); //主线程结束后对定时器无影响
//Timer t = new Timer(true);//定时器关联的线程为守护线程(主线程结束后,Timer线程关闭,Timer线程内未执行的定时器取消)
TimerTask task = new TimerTask() {
public void run() {
System.out.println(Thread.currentThread().getName()); //Timer-0
}
};
System.out.println(Thread.currentThread().getName()); //main
t.schedule(task, 3000, 2000); //3秒后立即执行定时器任务,以后每隔2秒执行一次
//t.schedule(task, time, 2000); //从time(Date类型)开始立即执行定时器任务,以后每隔2秒执行一次
//t.schedule(task, 3000); //3秒后执行定时器任务1次
//t.schedule(task, time); //到time(Date类型)时间的时候执行任务1次
}
}
11、MessageDigest
MessageDigest可以用来计算MD5、SHA1等hash值:
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest("password".getBytes(StandardCharsets.UTF_8));
String strMD5 = String.format("%035x", new BigInteger(1, hash));
System.out.println(strMD5); //0005f4dcc3b5aa765d61d8327deb882cf99