重整旗鼓学Java之常用类

字符串相关类

String

String类: 代表字符串字面值(如“abc”)都为此类的实例实现

String是一个final类,代表不可变的字符串序列

字符串是常量,用双引号引起来表示。他们的值在创建之后不能更改

String对象的字符内容是存储在一个字符数组value[]中的。

/**
	* String: 字符串,使用了一对""引起来表示。
	* String 声明为final的,不可被继承
	* String 实现了Serializable接口: 可序列化的,表示字符串是支持序列化的。
	* String 实现了Comparable接口: 表示可比较大小
	* String 内部定义了final char[] value用于存储字符串数据
	* String 代表一个不可变的字符序列。简称: 不可变性
	*/
public class StringTest{
	@Test
	public void test1(){
		String s1 = "abc";
		String s2 = "abc";
		// 通过字面量的方式给一个字符串赋值,此时字符串值声明在字符串常量池中
		// 字符串常量池中是不会存储相同内容的字符串的。
		System.out.println(s1 == s2);
		s1 = "hello";

		System.out.println(s1);
		System.out.println(s2);
	}
}
// 这一块的基本和python基本数据类型中的String一致虽然java中他不是基本数据类型。

String对象的创建

它比较特殊,它虽然是个类,但是可以直接通过字面量的形式String s = "abc"这种形式去赋值,这样一来,那它原本的new方法呢?直接通过字面量的形式赋值呢区别在于,字面量赋值会在方法区中的字符串常量池中赋值,但是new对象的形式是在堆空间中赋值

@Test
public void test2(){
	//这种叫通过字面量赋值,此时s1和s2的数据javaEE声明在方法区中的字符串常量池中
	String s1 = "javaEE";
	String s2 = "javaEE";
	// 通过new + 构造器的方式: 此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
	String s3 = new String("javaEE");
	String s4 = new String("javaEE");

	System.out.println(s1 == s2); // true
	System.out.println(s1 == s3); // false
	System.out.println(s1 == s4); // false
	System.out.println(s3 == s4); // false

	Person p1 = new Person("zhang", 12);
	Person p1 = new Person("zhang", 12);

	System.out.println(p1.name.equals(p2.name));// String的equals重写了,是比较的内容
	System.out.println(p1.name == p2.name);// 注意是通过字面量的方式赋值的。
	
}
// 构造器的方法去创建首先s3是指向的堆空间这个对象的地址值,这个对象是一个引用数据类型,引用的是
// 常量池中的常量的地址值。
public class Person{
	String name;
	int age;
	
	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}

	public Person(){

	}
}

面试题

String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?

两个,堆空间new的对象结构,常量池中char[]数据

不同拼接操作对比

public void test3(){
	String s1 = "javaEE";
	String s2 = "hadoop";

	String s3 = "javaEEhadoop";
	String s4 = "javaEE" + "hadoop";
	String s5 = s1 + "hadoop";
	String s6 = "javaEE" + s2;
	String s7 = s1 + s2;

	System.out.println(s3 == s4);// true
	System.out.println(s3 == s5);// false
	System.out.println(s3 == s6);// false
	System.out.println(s3 == s7);// false
	System.out.println(s5 == s6);// false
	System.out.println(s5 == s7);// false
	System.out.println(s6 == s7);// false

	String s8 = s5.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
	System.out.println(s3 == s8);
}

结论:

常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。

只要其中有一个是变量,结果就在堆中。

如果拼接的结果调用intern()方法,返回值就在常量池中

思考:

public void test(){
	String s1 = "javaEEhadoop";
	String s2 = "javaEE";

	String s3 = s2 + "hadoop";
	System.out.println(s1 == s3); // false

	final String s4 = "javaEE";
	String s5 = s4 + "hadoop";
	System.out.println(s1 == s5);// true
	// 为啥呢? 这里要注意final关键字,加了这个关键字之后,s4就是常量了存储在方法区中。
}

面试题

public class StringTest {
	String str = new String("good");
	char[] ch = {'t','e','s','t'};

	public void change(String str,char ch[]){
		str = "test ok"'
		ch[0] = 'b';
	}

	public static void main(String[] args) {
		StringTest ex = new StringTest();
		ex.change(ex.str, ex.ch);
		System.out.print(ex.str + "and");//good
		System.out.println(ex.ch);// best
	}
}

String常用方法

length()返回字符串的长度

charAt()返回索引处的字符

isEmpty()判断是否是空

toLowerCase()转小写

toUpperCase()转大写

trim()返回字符串的副本,忽略前导空白和尾部空白

equals: 比较内容

equalsIgnoreCase():与equlas方法类似 但是忽略大小写

concat(String str): 将指定字符串连接到此字符串的结尾。等价于用"+"

compareTo(String anotherString):比较两个字符串大小

substring(int beginIndex): 返回一个新的字符串,它是此字符串的从beginIndex

substring(int beginindex,int endindex):截取

我挑几个我自己不太熟悉的写一下案例

@Test
public void test1(){
	String s1 = "helloworld";
	String s2 = "";
	s2.isEmpty();// true 本质是判断它的长度是不是 == 0
	
	String s3 = "  hell o wo r ld ";
	String s4 = s3.trim();// 我这个属实用的少,去除首位空格,
	System.out.println(s3);//  hell o wo r ld 
	System.out.println(s4);//hell o wo r ld

	String s5 = "abc";
	String s6 = new String("abd");
	System.out.println(s5.compareTo(s6));// 本质是char[]里面元素一个个去比较

	//substring 这个有点类似python的切片,都是包左不包右
}

需要关注的一些String方法

endsWith(String suffix): 测试是不是以指定字符串结束

startsWith(String prefix):是否以指定前缀开始

starsWith(String prefix, int toffset):从指定位置开始是否是以指定前缀开始

contains(CharSequence s):当字符串包含此char值序列时,返回true

indexOf(String str)返回子字符串在字符串中第一次出现的索引位置

indexOf(String str, int fromindex)

lastIndexOf(String str)

lastIndexOf(String str,int fromIndex)

这些index未找到都返回-1

replace(char oldChar,char newChar):给定的字符替换,返回新的字符串,

replace(CharSequence target,CharSequence replacement):给定的序列字符替换。

replaceAll(String regex,String replacement):使用给定的replacement替换满足正则的子字符串

replaceFirst(String regex,String replacement): 替换满足正则的第一个字符串。

matches(String regex):告知此字符串是否匹配给定的正则表达式

split(String regex):根据给定的正则表达式拆分此字符串

split(String regex,int limit):根据给定的正则表达式拆分此字符串 ,最多不超过n个,如果超过放到最后一个元素中

String和其他结构之间的转换

public void test1(){
	String str1 = "123";

	int num = Integer.parseInt(str1);

	String str = String.valueOf(num);
}

String 与char[]之间的转换

@Test
public void test2(){
	String str1 = "abc123";
	
	char charArray = str1.toCharArray();

	// char[]转换成String
	char[] arr = new char[]{'h','e','l','l','o'};
	String str2 = new String(arr);
	System.out.println(str2);
}

String与byte[]之间的转换

@Test
public void test3(){
	String str1 = "abc123";
	byte[] bytes = str1.getBytes();// 使用的是默认的字符集utf-8
	System.out.println(Arrays.toString(bytes));	//会转换成ascci码

	byte[] gbks = str1.getBytes("gbk");// 使用gbk编码
}

常见String算法题

  1. 模拟一个trim方法,去除字符串两端空格。
  2. 将一个字符串进行反转。将指定部分反转
  3. 获取一个字符在字符串中出现的次数
  4. 获取两个字符串中最大的相同子串
  5. 对字符串中字符进行自然顺序排序

StringBuffer和StringBuilder类

String是一个不可变的字符序列,底层会使用char[]来进行存储,而StringBuffer是可变的它里面的方法几乎都加上了synchronized,所以它算是线程安全,效率会相对而言低一些,它也是使用的char[]来进行存储,但是它没有加final。StringBuilde也是一个可变的,是jdk5.0新增的,但是线程不安全,效率会高一些,底层也是使用char[]存储。

@Test
public void test1(){
	StringBuffer sb1 = new StringBuffer("abc");
	sb1.setCharAt(0,'m');
	System.out.println(sb1);
}

问题来了,setCharAt方法没有返回值,怎么sb1这个字符串他本身还改变了呢?

先看StringBuffer

从它的空参构造器本身看起,它的构造的时候相当于直接在底层创建了一个长度是16的char[],有参的时候呢,其实也是先创建一个"xxx".length() + 16个长度的char[],也就是说,无论怎么样,在新建的时候,它都会给你留出16个长度的空位。

那问题来了,StringBuffer sb2 = new StringBuffer();System.out.println(sb2.length());输出的值是16吗?不是嗷!0嗷!它是每次有个count初始值是0,char[]每append一次就加一。

问题又来了,如果要添加的数据长度超过了16怎么办呢? 这时候就引入一个扩容的概念。其实每次添加的时候它都会调用一个ensureCapacityInternal的方法去确认长度是否还足够,如果不够就先把原有数组长度左移一位(value.length << 1)翻倍。然后加2,作为返回值,给原有的char[]去使用Arrays.copyOf()去扩容。

StringBuffer的常用方法

append(xxx):提供了很多append()方法,用于字符串拼接

delete(int start,int end)删除指定位置的内容

replace(int start,int end,String str),把开始到结束的位置换成str

insert(int offset,xxx)在指定位置插入xxx

reverse(): 把当前字符序列逆转

indexOf(String str)

substring(int start,int end):有返回值,但是没切割

length()

chaAt(int n)

setcharAt(int n,char ch)

大概就是几个: 增删改查插长度、遍历、

String、StringBuffer、StringBuild效率对比

public void test2(){
	long startTime = 0L;
	long endTime = 0L;
	String text = "";
	StringBuffer buffer = new StringBuffer("");
	StringBuild builder = new StringBuilder("");

	// 开始对比
	startTime = System.currentTimeMillis();
	for(int i = 0;i < 20000; i++) {
		buffer.append(String.valueOf(i));
	}
	endTime = System.currentTimeMillis();
	System.out.println("StringBuffer的执行时间" + (endTime - startTime));// 第二

	startTime = System.currentTimeMillis();
	for(int i = 0;i < 20000; i++) {
		builder.append(String.valueOf(i));
	}
	endTime = System.currentTimeMillis();
	System.out.println("StringBuilder的执行时间" + (endTime - startTime)); // 最小

	startTime = System.currentTimeMillis();
	for(int i = 0;i < 20000; i++) {
		text = text + i;
	}
	endTime = System.currentTimeMillis();
	System.out.println("String的执行时间" + (endTime - startTime)); // 最大
}

JDK8之前的日期时间API

首先要知道在java.lang.System类中提供了currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间的毫秒为单位的差,也就是时间戳

第二个结构就是Date类,表示特定的瞬间,精确到毫秒,使用无参构造器Date()创建的对象可以获取本地当前时间常用方法getTime()【java.sql.Date类下也有】

@Test
public void test2(){
	Date date1 = new Date(); // 创建了一个当前时间的Date对象
	System.out.println(date1.toString());// 显示当前星期、月、日、时分秒

	System.out.println(date1.getTime());// 和currentTimeMillis()的意思一样。

	// 构造器二 创建了一个指定时间的Date对象
	Date date2 = new Date(12342143241L);

	// 构造器三
	Date date3 = new Date(2010,1,13);//但是过期了,不推荐用了。

	java.sql.Date date3 = new java.sql.Date(12234234123L);// 创建了一个sql的Date对象 xxxx-xx-xx

	// java.sql.Date(子类)对象转成java.util.Date(父类)对象 --- 多态,直接传就是了

	// java.util.Date(父类)对象转成java.sql.Date(子类)
	// 情况一:
	Date date4 = new java.sql.Date(124234234L);
	java.sql.Date date5 = (java.sql.Date)date4;

	// 情况二:
	Date date6 = new Date();
	java.sql.Date date7 = new java.sql.Date(date6.getTime());
	
	
	
}

java.sql.Date对应着数据库中的日期型变量。

SimpleDateFormat

该类是一个不与语言环境有关的方式来格式化和解析日期的具体类

格式化与解析

public class DateTimeTest{
	@Test
	public void testSimpleDateFormat() throws ParseException {
		//实例化SimpleDateFormat -- 空参构造器
		SimpleDateFormat sdf = new SimpleDateFormat();

		// 格式化: 日期  -- > 字符串
		Date date = new Date();
		String format = sdf.format(date);

		// 解析 : 字符串 --- > 日期
		String str = "20-12-18 上午11:43";
		Date date1 = sdf.parse(str);// 这个是有异常需要自己去处理的,就是怕你传入的字符串不靠谱

		// 那万一我确实想传入其他格式的字符串怎么办?
		// 那就别调用空参构造器,去以字符串形式传入日期的格式"yyyy.MMMM.dd ......."等等
	}
}
// 如果是字符串"2020-09-08"怎么去转换成java.sql.Date呢,可以先用SimpleDateFormat转换成
// Date格式的,然后使用getTime()方法去声明一个sql.Date的对象

Calendar(日历类)

它是一个抽象类,所以不能实例化,但是可以调用getInstance()方法去获取对象。或者通过调用它的子类GregorianCalendar的构造器

使用

public class CalendarTest{
	@Test
	public void testCalendar(){
		// 1. 实例化
		// 方式一: 创建其子类(GregorianCalendar)的对象
		// 方式二: 调用他的getInstance() -- 其实还是GregorianCalendar类造的
		Calendar calendar = Calendar.getInstance();

		// 2. 常用方法
		// get()
		int days = calendar.get(Calendar.DAY_OF_MONTH);// 是通过这些常量,来获取具体的数据
		System.out.println(days);

		// set()
		calendar.set(Calendar.DAY_OF_MONTH,22);//设置今天是这个月的第几天
		days = calendar.get(Calendar.DAY_OF_MONTH);
		System.out.println(days);

		// add()
		calendar.add(Calendar.DAY_OF_MONTH,3);// 在今天是几号的基础上加几天
		days = calendar.get(Calendar.DAY_OF_MONTH);
		System.out.println(days);

		// getTime()
		Date date = calendar.getTime();
		System.out.println(date);

		// setTime() 
		Date date1 = new Date();
		calendar.setTime(date1);// 通过Date格式的时间设置现在这个日历的时间
		
	}

}

JDK8中新日期时间API

Date在引入Calendar类之后,就慢慢的被弃用了,但是Calendar并不比Date好用多少,上面这些学习没有看出来它的缺点: 主要的问题是

可变性: Calendar类里面还可以自己去设置去改时间,但是理论上时间和日期这种类应该是不变的

偏移性: Date中年份是从1900开始,而月份却是从0开始的

格式化: 格式化只对Date有用,Calendar则不行

此外,他们线程都不安全,不能处理闰秒(这他妈是个啥,我看了解释也没整懂)

然后就引入了

java.time - 包含值对象的基础包

java.time.chrono - 提供对不同的日历系统的访问

java.time.format - 格式化和解析时间和日期

java.time.temporal - 包括底层框架和扩展特性

java.time.zone - 包含时区支持的类

LocalDate、LocalTime、LocalDateTime的使用

public class JDK8DateTimeTest {
	@Test
	public void test1(){
		// now() 根据当前时间创建对象/指定时区的对象
		LocalDate localDate = LocalDate.now();
		LocalTime localTime = LocalTime.now();
		LocalDateTime localDateTime = LocalDateTime.now();

		System.out.println(localDate);// 2020-12-10
		System.out.println(localTime); // 15:12:21.890
		System.out.println(localDateTime);// 2020-12-10T15:12:21.890

		// of() 指定时间创建对象,不同于Date,它没有偏移量
		LocalDate localDate1 = LocalDate.now(2020,10,6,13,23,43);
		System.out.println(localDate1);

		// getXxx()// 只要你对象里面有这个,你就能通过这个方法获取到相应的值
		Syste.out.println(localDateTime.getDayOfMonth());
		Syste.out.println(localDateTime.getDayOfWeek());
		Syste.out.println(localDateTime.getMonth());
		Syste.out.println(localDateTime.getMonthValue());
		Syste.out.println(localDateTime.getMinute());

		// withXxx() 设置具体的时间
		LocalDate localDate1 = localDate.withDayOfMonth(22);// 不可变性,本身没变,但是localDate1变了。
		

		// plusXxx() // 同with一样,也是体现不可变性在原有的基础上加上
		LocalDateTime localDateTime3 = localDateTime.plusMonth(3);

		// minusXxx() // 同上,不过是减了
	}
}

Instant瞬时

有点类似Date,就是直接从1970到1月1日到现在的毫秒数

@Test
public void test2(){
	// 实例化一个对象当前时间
	Instant instant = Instant.now();
	System.out.println(instant);

	// atOffset(ZoneOffset offset)设置时区偏移量,比如我们在东八区
	OffsetDateTime offsetDateTime = instant.atOffset(ZonOffset.ofHours(8));
	System.out.println(offsetDateTime);

	// 获取从1970年1月1日0时0分0秒到现在的毫秒数 有点类似Date的getTime()
	long milli = instant.toEpochMilli();

	// 根据毫秒数实例化对象 例子的数字是瞎写的有点类似new Date(234132412L)
	Instant instant1 = Instant.ofEpochMilli(234132412L);
	
}

DateTimeFormatter

有点类似上面说的SimpleDateFormat,我是这么记忆的,旧版本有Date,为了格式化出了SimpleDateFormat,觉得不好用,就新增了Calendar,新版本里面的,Instant就和Date很像,LocalTime这些就和Calendar比较像,现在说的这个DateTimeFormatter自然和SimpleDateFormat比较像了,对比记忆一下,就没啥问题了。

@Test
public void test3(){
	// 实例化方式1:ISO_LOCAL_DATE_TIME\ISO_LOCAL_TIME_\ISO_LOCAL_DATA
	DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
	// 格式化,同理,也需要先来一个日期
	LocalDateTime localDateTime = LocalDateTime.now();
	String str1 = formatter.format(localDateTime);
	System.out.println(localDateTime);//"2020-12-18T15:42:18.797"

	// 解析 因为LocalDateTime其实是实现TemproalAccessor这个接口的一个类。
	TemproalAccessor parse = formatter.parse("2020-12-18T15:42:18.797");

	// 实例化方式2:FormatStyle.SHORT/FormatStyle.LONG/FormatStyle.MEDIUM:适用于LocalDateTime
	DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
	String str2 =	formatter1.format(localDateTime);
	System.out.println(str2);//20-12-18 下午3:47
	// ofLocalizedDate()

	// 实例化方式3: 重点ofPattern("yyyy-MM-dd hh:mm:ss E")
	DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
	String str4 = formatter3.format(LocalDateTime.now());
}

Java比较器

这个我使用的还是挺多的在java中经常会涉及到对象数组的排序,那么就涉及到对象之间比较的问题

java实现对象排序的方式有两种:

  • 自然排序:java.lang.Comparable
  • 定制排序:java.util.Comparator

Comparable接口的使用

其实我们很早就接触到他了,在String中,它是实现了Comparable接口的,比如compareTo()的方法,就给出了比较两个对象的方法

那怎么去重写这个compareTo(obj)呢?

如果当前对象this大于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回负数,如果当前对象this等于形参对象obj,则返回零。

Comparable的自然排序

/**
	* 商品类
	*/
public class Goods {
	private String name;
	private double price;

	public Goods(){

	}

	public Goods(String name,double price){
		this.name = name;
		this.price = price;
	}

	public double getPrice(){
		return price;
	}

	public void setPrice(double price){
		this.price = price;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}
	
	@Override
	public String toString(){
		return "Goods{" + "name='" + name + '\'' + ",price=" + price + '}';
	}
}

那我们现在要对商品这个对象来排序

public void test2(){
	Goods[] arr = new Goods[4];
	arr[0] = new Goods("鼠标", 200);
	arr[1] = new Goods("显示屏", 800);
	arr[2] = new Goods("键盘", 500);
	arr[3] = new Goods("主机", 5020);

	// 如果我们直接用工具类
	// Arrays.sort(arr);这个就会报错,说你传入的这些数组的元素不是一个Comparable
	// 那么我们呢可以自定义类去实现Comparable接口去重写这个CompareTo()的方法 -- 自然排序
}

那么我们把这个Goods去重写

// 先实现Comparable接口
public class Goods implements Comparable {
	private String name;
	private double price;

	public Goods(){

	}

	public Goods(String name,double price){
		this.name = name;
		this.price = price;
	}

	public double getPrice(){
		return price;
	}

	public void setPrice(double price){
		this.price = price;
	}

	public String getName(){
		return name;
	}

	public void setName(String name){
		this.name = name;
	}
	
	@Override
	public String toString(){
		return "Goods{" + "name='" + name + '\'' + ",price=" + price + '}';
	}

	// 然后在这里指明商品按什么进行排序
	@Override
	public int compareTo(Object o){
		if(o instanceof Goods){
			Goods goods = (Goods)o;
			if(this.price > goods.price){
				return 1;
			} else if(this.price < goods.price){
				return -1;
			} else {
				return 0;
			}
		}
		throw new RuntimeException("传入的类型不一致");
	}
}

只有当我们的Goods类中,实现了这个compareTo方法之后,它才能用Arrys.sort()方法进行排序。只要我们实现了compareTo之后,我们排序只需要往Arrys.sort()方法里面去扔,它自然而然就给我排好序了。

Comparator定制排序

当我们的Goods没有实现java.lang.Comparator接口又不方便改代码,比如Goods类被打到jar包了,我特么现在改的一个bug就是,产品直接把接口打到jar包了,但是它自己方法又有错,还让我找到指定的类了它才给我源码,气死了,主要是菜,不知道怎么才能找到指定的类。

它的重写规则和Comparable接口基本一致,不一样的是,Comparable接口实现是拿this去和形参比较大小,而Comparator的实现是去拿两个形参去比较大小,拿到底我们要怎么用呢?

@Test
public void test3(){
	String[] arr = new String[]{"AA","BB","CC","DD","EE","FF"};
	// 匿名接口对象
	Arrays.sort(arr,new Comparator(){
		@Override
		public int compare(Object o1,Object o2) {
			if(o1 instanceof String && o2 instanceof String){
				String s1 = (String) o1;
				String s2 = (String) o2;
				return -s1.compareTo(s2);	
			}
			throw new RuntimeException("输入的数据类型不一致!");
		}
	})
}
// 这里没有引用泛型,所以没办法只能先这样判断一下是不是同一个类

System类

代表系统,系统级的很多属性和方法都放在这个类内部,在lang包下,由于它构造器是private的,所以无法实例化这个类,它内部成员变量和方法都是static,所以可以很方便的直接调用

成员变量:

包含了三个成员变量in、out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)

成员方法:

native long currentTimeMills(),返回当前和标准时间的毫秒差

void exit(int status)该方法作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用这个方法可以在图形化界面实现程序退出的功能

void gc()该方法的作用是请求系统进行垃圾回收。至于系统是否立即回收,则看系统怎么想。

String getPropeety(String key)该方法的作用是获得系统中属性为key的属性对应的值,系统中常见的属性名以及属性作用如下表示

java.version —— java运行环境版本

java.home —— java安装目录

os.name —— 操作系统的名称

os.version ——操作系统的版本

user.name — — 账户名称

user.home —— 用户的主目录

user.dir —— 用户当前工作目录

Math类

lang包下的Math类提供了一系列静态方法用于数学计算。其方法参数和返回值一般为double型

abs —— 绝对值

acos,asin,atan,cos,sin,tan —— 三角函数

sqrt — 平方根

pow(double a,double b) —— a的b次幂

log —— 自然对数

exp —— e为底指数

max(double a,double b)

min(double a,double b)

random() —— 返回0.0到1.0的随机数

long round(double a) —— double型数据a转换为long型(四舍五入)

toDegress(double angrad) —— 弧度转角度

toRadians(double angeg) —— 角度转弧度

Biginteger与BigDecimal

Biginteger

Integer作为int的包装类,能存储的最大整型为2^31 - 1,long类也是有限的,最大为2^63 - 1,如果有更大的整数,不管是基本数据类型,还是包装类都无能为力了。

java.math包的BigInteger可以表示不可变的任意精度的整数。Biginteger提供所有Java的基本整数操作符的对应物,并提供了很多计算方法

BigInteger(String val):根据字符串构建BigInteger对象

常用方法:

public BigInteger abd():返回此BigInteger的绝对值的BigInteger

BigInteger add(BigInteger val):返回值为(this+val)的BigInteger

BigInteger subtract(BigInteger val):返回值为(this - val)的BigInteger

BigInteger multiply(BigInteger val): 返回值为(this * val)的BigInteger

BigInteger divide(BigInteger val):返回 (this / val)的BigInteger,整数相除只保留整数部分

BigInteger remainder(BigInteger val) : 返回其值为(this % val) 的BigInteger

BigInteger[] divideAndRemainder(BigInteger val):返回包含(this / val)后跟(this % val)的两个BigInteger的数组

BigInteger ****pow(int exponent):返回其值为(this^exponent)的BigInteger

BigDecimal

一般Float和Double类可以用来做科学计算或工程计算,但是在商业计算中,要求数字精度高,所有用到了java.math.BigDecimal类

BigDecimal类支持不可变、任意精度的有符号十进制定点数

构造器:

public BigDecimal(double val)

public BigDecimal(String val)

常用方法:

public BigDecimal add(BigDecimal augend)

public BigDecimal subtract(BigDecimal subtrahend)

public BigDecimal multiply(BigDecimal multiplicand)

// roundingMode有这么几个Static类型的值BigDecimal.ROUND_HALF_UP等

// scale代表小数点后几位小数

public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的成语消消乐 Java 代码示例: ```java import java.util.*; public class ChengYuXiaoXiaoLe { public static void main(String[] args) { String[] chengyu = {"天上人间", "人山人海", "海阔天空", "空空如也", "也就是说", "说一不二", "二话不说", "说三道四", "四面楚歌", "歌功颂德", "德高望重", "重整旗鼓", "鼓起勇气", "气吞山河", "河东狮吼", "吼声震天", "天下无敌", "敌不过我", "我行我素", "素不相识", "识趣的人", "人云亦云", "云淡风轻", "轻松愉快", "快人快语", "语重心长", "长话短说", "说来说去", "去而复返", "返老还童", "童叟无欺"}; int score = 0; int count = 0; int round = 1; while (true) { System.out.println("第" + round + "回合,当前得分:" + score); System.out.println("当前成语列表:"); for (int i = 0; i < chengyu.length; i++) { System.out.print(chengyu[i] + " "); } System.out.println(); Scanner scanner = new Scanner(System.in); System.out.println("请输入一个成语:"); String input = scanner.nextLine(); boolean found = false; for (int i = 0; i < chengyu.length; i++) { if (input.equals(chengyu[i])) { found = true; chengyu[i] = ""; score += input.length(); count++; break; } } if (!found) { System.out.println("输入的成语不合法或已被消除,请重新输入!"); } if (count == chengyu.length) { System.out.println("恭喜你,已经消除了所有成语!"); System.out.println("最终得分:" + score); break; } round++; } } } ``` 此代码实现了一个简单的成语消消乐游戏,通过在控制台输入成语进行游戏。游戏的规则是,输入的成语必须与列表中的成语相连(即第一个成语的最后一个字必须与第二个成语的第一个字相同),并且列表中的成语只能使用一次。每次输入一个成语,如果输入的成语合法且在列表中存在,则该成语将从列表中消除,并且得分将增加该成语的长度。当所有成语都被消除时,游戏结束,输出最终得分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值