Java常用类库(二)

大数字操作类

简介

  • 如果现在有两个非常大的数字要进行数学操作,数字已经超过了double的范围,那么只能利用字符串来表示,取出每一位字符变为数字后进行数学计算
  • 但是这种方式的难度较高,为了解决这样的问题,在Java里面提供了两个大数字操作类:java.math.BigInteger、java.math.BigDecimal,而这两个类是属于Number的子类。

大整数操作类:BigInteger

  • 刚才说了,如果数字较大,肯定按照String来处理,所以这一点可以通过BigInteger的构造方法看到
    • 构造:public BigInteger(String val);
  • BigInteger类之中定义的一些基本的数学计算:
    • 加法: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),数组第一个元素是商,第二个元素是余数;
    import java.math.BigInteger;
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		BigInteger bigA = new BigInteger("234809234801");
    		BigInteger bigB = new BigInteger("8939834789");
    		System.out.println("加法结果:" + bigA.add(bigB));
    		System.out.println("减法结果:" + bigA.subtract(bigB));
    		System.out.println("乘法结果:" + bigA.multiply(bigB));
    		System.out.println("除法结果:" + bigA.divide(bigB));
    		BigInteger result[] = bigA.divideAndRemainder(bigB);
    		System.out.println("商:" + result[0] + ",余数:" + result[1]);
    	}
    }
    

大小数操作类:BigDecimal

  • BigDecimal类表示的是大小数操作类,但是这个类也具备了与之前同样的基本计算方式
  • 在实际的工作之中,使用这个类最多的情况是进行准确位数的四舍五入操作,如果要完成这一操作需要关心BigDecimal类中的以下定义:
    • 构造:public BigDecimal(double val);
    • 除法:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode);
    • 进位模式:public static final int ROUND_HALF_UP。
  • 完成准确位的四舍五入操作
    import java.math.BigDecimal;
    class MyMath {
    	public static double round(double num, int scale) {
    		BigDecimal big = new BigDecimal(num);
    		BigDecimal result = big.divide(new BigDecimal(1), scale,
    		BigDecimal.ROUND_HALF_UP);
    		return result.doubleValue(); // Number类的方法
    	}
    }
    
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		System.out.println(MyMath.round(15.5, 0)); // 16
    		System.out.println(MyMath.round(-15.5, 0)); // -15
    		System.out.println(MyMath.round(168.98765, 2)); // 168.99
    	}
    }
    
  • 这个代码在日后的开发之中,就作为工具代码出现了,可以不用自己再去编写。

数组操作类:Arrays

排序操作:java.util.Arrays.sort(数组名称)

  • 对于Arrays类一直是进行数组排序的操作,而Arrays类是定义在java.util包下的一个操作类,在这个类之中定义了所有的与数组有关的基本操作:二分查找、相等判断、填充等。
    import java.util.Arrays;
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		int[] dataA = new int[] { 1, 2, 3 };
    		int[] dataB = new int[] { 1, 2, 3 };
    		System.out.println(Arrays.equals(dataA, dataB));
    		Arrays.fill(dataA, 3) ;	// 填充数组
    		System.out.println(Arrays.toString(dataA));
    	}
    }
    
  • 上面的代码只是作为Arrays类的基本使用,但是在Arrays类之中定义了一个方法:
    • 为对象数组排序:public static void sort(Object[] a)。
    import java.util.Arrays;
    class Person {
    	private String name ;
    	private int age ;
    	public Person(String name,int age) {
    		this.name = name ;
    		this.age = age ;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]\n";
    	}
    }
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		Person per[] = new Person[] { new Person("张三", 20),
    				new Person("李四", 19), new Person("王五", 21) };
    		Arrays.sort(per) ;	// 排序
    		System.out.println(Arrays.toString(per));
    	}
    }
    
  • 这个时候没有任何的语法错误,即:程序的代码是正确的,但是在程序执行的时候出现了以下的问题: Exception in thread “main” java.lang.ClassCastException: cn.Hello.demo.Person cannot be cast to java.lang.Comparable
    明确的告诉用户现在发生了“ClassCastException”,类转换异常,Person类不能变为Comparable实例。

比较器

简介

  • 如果现在要想为一组对象进行排序,那么必须有一个可以区分出对象大小的关系操作,而这个操作在Java之中就是利用比较器完成的。
    常用比较器:Comparable
  • 如果要为对象指定比较规则,那么对象所在的类必须实现Comparable接口,下面是这个接口的定义:
    public interface Comparable<T> {
    	public int compareTo(T o);
    }
    
  • 要排序的数组所在的类一定要实现此接口,此接口返回的是int型数据,而用户覆写此方法的时候只需要返回三种结果:1(>0)、-1(<0)、0(=0)即可。
    import java.util.Arrays;
    class Person implements Comparable <Person> {
    	private String name ;
    	private int age ;
    	public Person(String name,int age) {
    		this.name = name ;
    		this.age = age ;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]\n";
    	}
    	@Override
    	public int compareTo(Person o) {
    		if (this.age > o.age) {
    			return 1;
    		} else if (this.age < o.age) {
    			return -1;
    		} else {
    			return 0;
    		}
    	}
    }
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		Person per[] = new Person[] { new Person("张三", 20),
    				new Person("李四", 19), new Person("王五", 21) };
    		Arrays.sort(per) ;	// 排序
    		System.out.println(Arrays.toString(per));
    	}
    }
    
  • 注意:不管是何种情况下,只要牵扯到对象数组排序的操作,永远都是比较器Comparable。

挽救的比较器

  • 上面使用的Comparable实际上是在一个类定义的时候就已经具备的功能了,但是如果说现在一个类已经定义完成了。
    class Person {
    	private String name ;
    	private int age ;
    	public Person(String name,int age) {
    		this.name = name ;
    		this.age = age ;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]\n";
    	}
    	public int getAge() {
    		return age;
    	}
    	public String getName() {
    		return name;
    	}
    }
    
  • 假如这个类在设计之初并没有考虑到排序的要求,可是后来又需要进行排序,但是以上的类已经无法修改了,那么如何使用Arrays.sort()排序呢?为了解决这样的问题,在java里面又提供了另外一个比较器接口:java.util.Comparator接口,这个接口的定义如下:
    public interface Comparator<T> {
    	public int compare(T o1, T o2);
    	public boolean equals(Object obj);
    }
    
    在compare()方法上存在了两个参数用于比较大小,而要想使用这个接口,需要单独定义一个比较规则类。
    /**
     *专门为Person类补救一个比较规则类
      */
    class PersonComparator implements Comparator<Person> {
    	@Override
    	public int compare(Person o1, Person o2) {
    		if (o1.getAge() > o2.getAge()) {
    			return 1;
    		} else if (o1.getAge() < o2.getAge()) {
    			return -1;
    		} else {
    			return 0;
    		}
    	}
    }
    
  • 如果要进行排序的话,依然使用Arrays类的sort()方法:public static void sort(T[] a, Comparator<? super T> c)
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		Person per[] = new Person[] { new Person("张三", 20),
    				new Person("李四", 19), new Person("王五", 21) };
    		Arrays.sort(per, new PersonComparator()); // 排序
    		System.out.println(Arrays.toString(per));
    	}
    }
    
  • 很明显,使用Comparator要比Comparable麻烦许多,所以以后别使它。

面试题:请解释Comparable和Comparator的区别?(请解释两种比较器的区别)

  • java.lang.Comparable是在一个类定义的时候默认实现好的接口,里面只有一个compareTo()方法;
  • java.util.Comparator是需要单独定义一个比较的规则类,里面有两个方法;compare()、equals()。

Binary Tree,二叉树

  • 二叉树是一种排序的基本的数据结构,而如果要想为多个对象进行排序,那么就必须可以区分出对象的大小,那么就必须依靠Comparable接口完成。
  • 二叉树的基本原理:取第一个元素作为根节点,之后每一个元素的排列要求:如果比根节点小的数据放在左子树,如果比根节点大的数据放在右子树,在输出的时候采用中序遍历(左-根-右)的方式完成。
  • 但是,不管是何种方式操作,这种数据结构的实现永远都需要依靠节点类,而这个时候的节点类要保存两个子节点:左、右。
    class Student implements Comparable<Student> {
    	private String name;
    	private int age;
    	public Student(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]\n";
    	}
    	@Override
    	public int compareTo(Student o) {
    		if (this.age > o.age) {
    			return -1;
    		} else if (this.age < o.age) {
    		return 1;
    		} else {
    			return 0;
    		}
    	}
    }
    class BinaryTree {
    	@SuppressWarnings("rawtypes")
    	private class Node {
    		private Comparable data;
    		private Node left;
    		private Node right;
    		public Node(Comparable data) {
    			this.data = data;
    		}
    		@SuppressWarnings("unchecked")
    		public void addNode(Node newNode) {
    			if (this.data.compareTo(newNode.data) < 0) {
    				if (this.left == null) { // 没有左子树
    					this.left = newNode;
    				} else {
    					this.left.addNode(newNode);
    				}
    			} else {
    				if (this.right == null) {
    					this.right = newNode;
    				} else {
    					this.right.addNode(newNode);
    				}
    			}
    		}
    		public void printNode() {
    			if (this.left != null) {
    				this.left.printNode();
    			}
    			System.out.println(this.data);
    			if (this.right != null) {
    				this.right.printNode();
    			}
    		}
    	}
    	private Node root; // 根节点
    	public void add(Student data) {
    		if (data == null) {
    			return;// 返回调用处
    		}
    		Node newNode = new Node(data); // 将数据封装为节点
    		if (this.root == null) { // 没有根节点
    			this.root = newNode;
    		} else { // 保存到合适的位置
    			this.root.addNode(newNode);
    		}
    	}
    	public void print() {
    		if (this.root != null) {
    			this.root.printNode();
    		}
    	}
    }
    public class BinaryTreeDemo {
    	public static void main(String[] args) {
    		BinaryTree tree = new BinaryTree();
    		tree.add(new Student("张三", 20));
    		tree.add(new Student("李四", 19));
    		tree.add(new Student("王五", 21));
    		tree.print();
    	}
    }
    

对象克隆Cloneable

简介

  • 克隆就是对象的复制操作,在Object类中存在一个clone()方法:
    克隆
  • 克隆方法:protected Object clone() throws CloneNotSupportedException;
  • 但是在这个方法上抛出了一个“CloneNotSupportedException”,不支持的克隆异常,这个异常表示的是要克隆对象的类必须实现Cloneable接口,但是这个接口没有任何的方法,这个接口属于标识接口,只表示一种能力。
    class Person implements Cloneable{	// 表示一种能力,没有方法覆写
    	private String name;
    	private int age;
    	public Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]\n";
    	}
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
    		return super.clone();	// 调用父类克隆
    	}
    }
    public class TestDemo {
    	public static void main(String[] args) throws Exception {
    		Person per = new Person("张三", 20) ;
    		Person p = (Person) per.clone() ;
    		p.setName("王五") ;
    		System.out.println(per);
    		System.out.println(p);
    	}
    }
    
发布了109 篇原创文章 · 获赞 47 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43934607/article/details/103542624