Java系列(十六)__Java常用类库(2)

Java系列(十六)__Java常用类库(2)


1、大数字操作类:BigInteger、BigDecimal

如果说现在有两个非常大的数字(超过了double范围)要进行数学的加法计算,你该怎么做?可以使用字符串保存数字,而后按照每个字符进行手工的处理数学计算。但是这样的复杂度非常的高,为此,在Java里面专门提供了一个java.math包,此包之中提供有两个大数字操作类:BigInteger(大整数操作类)、BigDecimal(大小数操作类)。

1、   大整数操作类:BigInteger

         BigInteger是Number的子类,但是在使用的时候肯定不用转为Number类型,在BigInteger类之中定义的构造方法:public BigInteger(String val),因为数据量一大,肯定使用String表示;

范例:完成四则运算

package cn.mldn.demo;

import java.math.BigInteger;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        BigInteger bigA = new BigInteger("4238903289023809238097890") ;

        BigInteger bigB = new BigInteger("98234789234") ;

        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]);

        System.out.println(bigA.pow(Integer.MAX_VALUE));

    }

}

         以上只是针对于BigInteger类做了一个演示,但是这样的代码意义不大,而且也没使用的环境,如果你在工作之中,如果真遇见了数学问题,一定要去找数学公式第三方开发包。

2、   大小操作类:BigDecimal

         此类的操作与BigInteger类基本是相同的,也提供有基本的数学计算,但是与这些数学计算相比,BigDecimal类有一个非常重要的功能。

         Math类之中的round()方法进行四舍五入操作过程之中,采用的是所有小数点全部进位,不能保留小数位,但是很多时候这样的做法是不可取,例如:如果某家公司的年收入是按照亿计算,今年收获了5.321亿美金,按照Math.round()结果就成了5亿,所以Math.round()是一个不可能使用的操作,这个时候只能够利用BigDecimal类完成。

         在BigDecimal类里面提供有一个除法操作:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

                   · 第一个参数:被除数,此处也应该是BigDecimal类型;

                   · 第二个参数:保留的小数位数;

                   · 第三个参数:进位模式(public static final int ROUND_HALF_UP)。

范例:实现准确的四舍五入操作

package cn.mldn.demo;

import java.math.BigDecimal;

class MyMath {

   

    public static double round(double num,int scale) {

        BigDecimal bigNum = new BigDecimal(num) ;   // 只有变为BigDecimal才可以调用divide()方法

        BigDecimal result = bigNum.divide(new BigDecimal(1), scale,

                BigDecimal.ROUND_HALF_UP);

        return result.doubleValue() ;

    }

}

public class TestDemo {

    public static void main(String[] args)throws Exception {

        System.out.println(MyMath.round(7809.652198, 2));

        System.out.println(MyMath.round(7809.652198, 1));

        System.out.println(MyMath.round(-13.5, 0));

    }

}

         此代码是在工作上使用最多的四舍五入操作模式,如果有需要代码直接使用。





2、Arrays类

“java.util.Arrays.sort()”是一个数组排序操作,实际上这一个操作就是调用了java.util包中Arrays类的sort()方法完成的,而Arrays是一个数组操作的工具类(数组一般使用较少,所以此工具类意义不大)。

范例:使用Arrays类

package cn.mldn.demo;

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, 9);

        System.out.println(Arrays.toString(dataA));

    }

}

         随着数组的使用减少,此类的操作也越来越少。




3、比较器

在之前接触过了Arrays类,那么下面来观察在Arrays类之中存在的一个方法:

· 对象数组排序:public static void sort(Object[] a);

范例:实现排序

package cn.mldn.demo;

import java.util.Arrays;

class Person {

    private String name ;

    private int age ;

    public Person(String name,int age) {

        this.name = name ;

        this.age = age ;

    }

    public String toString() {

        return "姓名:" +this.name + ",年龄:" + this.age ;

    }

}

public class TestDemo {

    public static void main(String[] args)throws Exception {

        Person per[] = new Person[] { new Person("张三", 20),

               new Person("李四", 18), new Person("王五", 25) };

        Arrays.sort(per);   // 排序

        for (int x = 0; x < per.length; x++) {

            System.out.println(per[x]);

        }

    }

}

Exception in thread "main" java.lang.ClassCastException: cn.mldn.demo.Person cannot be cast to java.lang.Comparable

         现在发现此时需要让Person类实现Comparable接口,而这就是一个比较器。

3.1、Comparable接口(核心)

         java.lang.Comparable接口是一个最为常用的比较器,那么此接口定义如下:

public interface Comparable {

         public int compareTo(T o) ;

}

         在Comparable接口之中发现只有一个compareTo()方法,而此方法可以返回三种类型的数据:-1(小)、0(等)、1(大)。

         在之前学习String类的时候也学习过compareTo()方法,当时的方法是可以进行大小判断的。

范例:使用比较器

package cn.mldn.demo;

import java.util.Arrays;

class Person implements Comparable {

    private String name ;

    private int age ;

    public Person(String name,int age) {

        this.name = name ;

        this.age = age ;

    }

    public String toString() {

        return "姓名:" +this.name + ",年龄:" + this.age ;

    }

    @Override

    public int compareTo(Person o) {

        if (this.age > o.age) {

           return 1 ;

        } else if (this.age < o.age) {

           return -1 ;

        }

        return 0;

    }

}

public class TestDemo {

    public static void main(String[] args)throws Exception {

        Person per[] = new Person[] { new Person("张三", 20),

               new Person("李四", 18), new Person("王五", 25) };

        Arrays.sort(per);   // 排序

        for (int x = 0; x < per.length; x++) {

            System.out.println(per[x]);

        }

    }

}

         以后只要是一组对象的大小比较一定使用Comparable接口。

3.2、Binary Tree(了解)

         既然已经知道了对象之间的大小比较操作,那么就可以利用此概念实现二叉树开发,二叉树的基本原则如下:

                   · 一个节点下可以保存两个节点,分别称为左子树和右子树;

                   · 取第一个数据作为根节点,比根节点小的数据要放在左子树上,比根节点大的数据要放在右子树上;

                   · 在进行输出的时候按照中序遍历(左-中-右)进行数据的取出。

范例:下面将利用Comparable实现二叉树操作

         · 大小关系利用Comparable接口的compareTo()方法实现。

package cn.mldn.test;

class Person implements Comparable {

    private String name;

    private int age;

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

    public String toString() {

        return "姓名:" +this.name + ",年龄:" + this.age;

    }

    @Override

    public int compareTo(Person o) {

        if (this.age > o.age) {

           return 1;

        } else if (this.age < o.age) {

           return -1;

        }

        return 0;

    }

}

@SuppressWarnings("rawtypes")

class BinaryTree {

    private class Node { // 一定要存在节点类

        private Comparable data; // 必须排序的是Comparable接口对象

        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 toArrayNode() {

           if (this.left != null) { // 有左子树

               this.left.toArrayNode();

            }

            BinaryTree.this.retData[BinaryTree.this.foot++] =this.data;

           if (this.right != null) {

               this.right.toArrayNode();

            }

        }

    }

    // ======================================

    private Node root; // 根节点

    private int count ; // 统计对象的保存个数

    private int foot ;  // 操作脚标

    private Object [] retData ;

    public void add(Comparable data) {

        if (data ==null) {

           return;

        }

        Node newNode = new Node(data); // 将新的数据变为一个节点

        if (this.root ==null) {    // 根节点没有数据

           this.root = newNode ;   // 新的节点将作为根节点存在

        } else {    // 要保存在合适的节点中

           this.root.addNode(newNode);

        }

        this.count ++ ; // 保存个数加一

    }

    public Object[] toArray() {

        if (this.root ==null) {

           return null ;

        }

        this.foot = 0 ;

        this.retData =new Object [this.count] ;    // 以保存大小开辟数组

        this.root.toArrayNode();

        return this.retData ;

    }

}

public class BinaryTreeDemo {

    public static void main(String[] args) {

        BinaryTree bt = new BinaryTree() ;

        bt.add(new Person("张三",20));

        bt.add(new Person("李四",18));

        bt.add(new Person("王五",25));

        Object [] data = bt.toArray() ;

        for (int x = 0; x < data.length; x++) {

            System.out.println(data[x]);

        }

    }

}

         如果日后笔试之中有人问:请写个二叉树,李老师讲过,我不会。

3.3、挽救的比较器:Comparator(了解)

         在工作之中如果使用到比较器,肯定首选的是Comparable,但是Comparable有一个特点,它必须在一个类定义的时候就实现好接口,可是如果有这样一种情况,一个类已经开发完成了,并且此类不允许再做出任何修改,此类在先期设计的时候没有考虑对象数组的排序问题,后期又提出了此问题。但是代码已经不能变更,那么这个时候如何排序呢?
范例:开发好的类

class Person {

    private String name ;

    private int age ;

    public Person(String name,int age) {

        this.name = name ;

        this.age = age ;

    }

    public String toString() {

        return "姓名:" +this.name + ",年龄:" + this.age ;

    }

    public String getName() {

        return name;

    }

    public int getAge() {

        return age;

    }

}

         Person类已经开发完成,并且打包后交给客户使用了,但是后来需要进行对象数组排序,那么这个时候由于Person类无法修改了,那么只能够采用另外一种比较器:java.util.Comparator接口,此接口定义如下。

public interface Comparator {

    public int compare(T o1, T o2) ;

    public boolean equals(Object obj) ;

}

范例:定义专门的比较规则

class PersonComparator implements Comparator {

    @Override

    public int compare(Person o1, Person o2) {

        if (o1.getAge() > o2.getAge()) {

           return -1 ;

        } else if (o1.getAge() < o2.getAge()) {

           return 1 ;

        }

        return 0;

    }

}

         此类只能够为Person类服务。随后如果要排序的时候在Arrays类有如下一个方法:

                   · 排序:public static void sort(T[] a, Comparator




4、正则表达式

离散数学是正则的理论基础,有想弄明白的,可以去研究一下。正则是一种简化的验证手段,例如,现在完成这样的一个代码。

范例:要求判断一个字符串是否由数字组成

         · 思路:将字符串变为字符数组,而后每个字符进行依次判断。

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String num = "12a3" ;

        System.out.println(isNumber(num));

    }

    public static boolean isNumber(String str) {

        char [] data = str.toCharArray() ;

        for (int x = 0; x < data.length; x++) {

           if (data[x] > '9' || data[x] < '0') {

               return false ;

            }

        }

        return true ;

    }

}

         但是这样一个非常简单或者说是简单到极点的验证写出了八行代码,如果再复杂一点呢?代码量会更多。

范例:利用正则操作

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String num = "123" ;

        System.out.println(num.matches("\\d+"));

    }

}

         发现如果在验证操作上使用正则符号进行匹配,则代码量可以非常少,而“"\\d+"”就是正则表达式。

         正则表达式最早是在Linux下发展起来的,在JDK 1.4之前,如果需要使用到正则那么要通过apache下载正则的应用包。而从JDK 1.4开始,Java正式支持了正则的开发,同时给出了一个java.util.regex开发包,提供正则的操作类。

         但是需要注意的是,在java.util.regex包里面只提供有两个核心类:

                   · java.util.regex.Pattern:正则标记编译类;

                   · java.util.regex.Matcher:正则匹配操作;

         而在开发之中很少去直接使用以上的两个类,一般都使用String类完成,因为从JDK 1.4之后开始,String类之中多了正则的支持,同时提供了以下支持正则的开发方法。

No.

方法名称

类型

描述

1

public boolean matches(String regex)

普通

正则验证

2

public String replaceAll(String regex, String replacement)

普通

全部替换

3

public String replaceFirst(String regex, String replacement)

普通

替换首个

4

public String[] split(String regex)

普通

全拆分

5

public String[] split(String regex, int limit)

普通

部分拆分

         下面的讲解以String类之中几个操作方法为主。

4.1、正则符号(背,死了都要会)

         如果要操作正则,那么必须使用一系列的正则匹配符号,而所有的正则匹配符号都在java.util.regex.Pattern类提供。

1、   表示单个字符(每出现一个只表示一位)

         · x:表示只能由x组成;

         · \\:表示转义字符“\”;

         · \t:匹配“tab”键;

         · \n:匹配换行;

2、   表示字符的选用范围(每出现一个只表示一位)

         · [abc]:表示可能是a、b、c中的任意一个;

         · [^abc]:表示不是a、b、c中的任意一个;

         · [a-zA-Z]:表示任意的一位字母,可能是大写或小写;

         · [0-9]:表示任意的一位数字;

3、   简化表达式(每出现一个只表示一位)

         · .:表示任意的一位字符;

         · \d:表示是一位数字,相当于“[0-9]”;

         · \D:表示不是一位数字, 相当于“[^0-9]”;

         · \s:表示是任意的一位空格;

         · \S:表示不是任意的一位空格;

         · \w:表示是大小写字母、数字、_中的任意一位,相当于“[a-zA-Z0-9_]”;

         · \W:表示不使大小写字母、数字、_中的任意一位,相当于“[^a-zA-Z0-9_]”;

4、   边界匹配

         · ^:写在正则之前,表示正则开始;

         · $:写在正则最后,表示正则结束;

5、   数量表示:如果没有数量,每一个出现的标记只能表示一位

         · 正则?:表示此正则规范只能够出现0次或1次;

         · 正则*:表示此正则出现0次、1次或多次;

         · 正则+:表示此正则出现1次或多次;

         · 正则{n}:表示此正则出现正好n次;

         · 正则{n,}:表示此正则出现n次以上;

         · 正则{n,m}:表示此正则出现n ~ m次;

6、   逻辑操作符

         · 正则X正则Y:表示正则X判断后执行正则Y;

         · 正则X|正则Y:表示两个正则二选一;

         · (正则):包含多个正则,成为一组;

4.2、通过String类来操作正则

         正则的所有操作方法都通过String类完成,所以下面将通过一些代码,通过String来操作正则。

范例:字符串替换

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String num = "fajkljkl32890*()jlk3809F*)(&w(*r&)(*4379RF8SD09" ;

        String regex = "[^a-zA-Z]" ;

        System.out.println(num.replaceAll(regex, ""));

    }

}

范例:字符串拆分

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String num = "a1b22c333d44444e5555555f66666666g" ;

        String regex = "\\d+" ;

        String result [] = num.split(regex) ;

        for (int x = 0; x < result.length; x++) {

            System.out.println(result[x]);

        }

    }

}

范例:现在用户名由字母、数字、_所组成,要求其范围在6~15位

         · 正则:[a-zA-Z0-9_] = \w;

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String num = "hello123" ;

        String regex = "\\w{6,15}" ;

        System.out.println(num.matches(regex));

    }

}

范例:现在某个学校的学生成绩要求按照“姓名:年龄:生日:成绩”,那么这样的数据可以出现多条,多条纪录之间使用“|”分隔,例如“SMITH:20:1990-09-15:90.9|ALLEN:19:1991-11-11:89.6|TONY:21:1989-07-28:100”。

         那么下面首先要进行问题的拆分,因为这个验证之中包含有许多的小规则:

         · 规则一:验证姓名,不设置长度限制(一位或多位,使用+表示);

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "SMITH" ;

        String regex = "[a-zA-Z]+" ;

        System.out.println(str.matches(regex));

    }

}

         · 规则二:验证年龄,年龄是一个数字,长度范围1 ~ 3位;

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "19" ;

        String regex = "\\d{1,3}" ;

        System.out.println(str.matches(regex));

    }

}

         · 规则三:验证生日,生日是数字组合

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "1998-08-01" ;

        String regex = "\\d{4}-\\d{2}-\\d{2}" ;

        System.out.println(str.matches(regex));

    }

}

         · 规则四:验证小数,成绩最多3位,小数位最多2位。

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "98.12" ;

        String regex = "\\d{1,3}(\\.\\d{1,2})?" ;

        System.out.println(str.matches(regex));

    }

}

         · 组合验证规则:

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "SMITH:20:1990-09-15:90.9" ;

        String regex= "[a-zA-Z]+:\\d{1,3}:\\d{4}-\\d{2}-\\d{2}:\\d{1,3}(\\.\\d{1,2})?" ;

        System.out.println(str.matches(regex));

    }

}

         · 满足于多组信息的操作;

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "SMITH:20:1990-09-15:90.9|ALLEN:19:1991-11-11:89.6|TONY:21:1989-07-28:100" ;

        String regex = "([a-zA-Z]+:\\d{1,3}:"

                + "\\d{4}-\\d{2}-\\d{2}:"

                + "\\d{1,3}(\\.\\d{1,2})?\\|?)+" ;

        System.out.println(str.matches(regex));

    }

}

范例:验证email地址,email地址的验证规则如下:

         · 用户名只能够以字母、数字、_、.组成;

         · 用户名只能够以字母开头;

         · 用户名的长度要求在6~20位之间;

         · 域名只能是:.com、.cn、.net、.com.cn、.net.cn、.edu、.gov;


package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args)throws Exception {

        String str = "[email protected]" ;

        String regex = "[a-zA-Z][a-zA-Z0-9_\\.]{5,19}"

                + "@[a-zA-Z-0-9]+\\."

                + "(com|cn|net|gov|edu|com\\.cn|net\\.cn)" ;

        System.out.println(str.matches(regex));

    }

}

         虽然从感觉上看这些符号组合比较麻烦,但是习惯了就好,可是应该知道正则的出现让代码简化了不少,尤其是针对于验证操作。




5、反射机制

我们在正常的使用过程之中只关心类产生对象,而后通过对象调用类之中的方法,可是,除了这种传统的方式外,也可以利用反射操作。

5.1、认识反射

         既然有反,那么一定存在有正,正是指的通过类产生对象,而后通过对象执行操作。而反呢?通过对象找到他所在的类的信息。所有的对象都支持反这一操作,因为Object类有一个方法:public final Class




你可能感兴趣的:(Java系列(十六)__Java常用类库(2))