• Java语言基础常用对象API(二)泛型、Map集合


    泛型

    是JDK1.5出现的安全机制。

    好处:
    1.将运行时期的问题ClassCastException转到了编译时期;
    2.避免了强制转换的麻烦;

    <> 什么时候用?        当操作的引用数据类型不确定的时候,就使用<>,将要操作的引用数据类型传入即可。
    <>就是一个用于接收具体引用数据类型的参数范围。

    在程序中,只要用到了带有<>的类或者借口,就要明确传入的具体引用数据类型;
    泛型技术是给编译器使用的技术,用于在编译时期确保类型的安全;
    运行时,会将泛型去掉,生成的class文件中不带有泛型。这个称为泛型的擦除。
    为什么擦除?    因为为了兼容运行时的类加载器。

    泛型的补偿:在运行时,通过获取元素的类型对进行转换动作,不需要使用者再进行强制转换。

    当方法静态时,不能访问类上定义的泛型,如果静态方法使用方法, 只能将泛型定义在方法上。
    当定义了泛型时,不能使用具体的方法。

    泛型使用示例:

    package cn.ticast.p4.generic.define.demo;
    
    public class GenericDemo4 {
        public static void main(String[] args){
            Tool<String> tool=new Tool<String>();
            
            tool.show(new Integer(4));
            tool.show("abc");
            tool.print("hahah");
            Tool.method("haha");
        }
    }
    
    
    package cn.ticast.p4.generic.define.demo;
    
    //jdk1.5以后,使用泛型来接收类中要操作的引用数据类型
    //泛型类:当类中操作的引用数据类型不确定时,使用泛型来表示
    public class Tool<QQ>{
        private QQ q;
    
        public QQ getObject() {
            return q;
        }
    
        public void setObject(QQ object) {
            this.q = object;
        }
        
        /**
         * 将泛型定义在方法上
         * @param str
         */
        public <w> void show(w str){
            System.out.println("show:"+str);
        }
        public void print(QQ str){
            //System.out.println("print:"+str.length());//错误,当定义了泛型时,不能使用具体的方法。
            System.out.println("print:"+str);
        }
        
        /**
         * 当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,
         * 只能将泛型定义在方法上
         */
        public static <Y> void method(Y obj){//静态方法不需要对象
            System.out.println("method:"+obj);
        }    
    }
    
    
    

    泛型接口示例:

    package cn.ticast.p4.generic.define.demo;
    
    public class GenericDefineDemo5 {
        public static void main(String[] args) {
            InterImpl1 in=new InterImpl1();
            in.show("abc");
            
            InterImpl2<Integer> in2=new InterImpl2<Integer>();
            in2.show(5);
        }
    
    }
    
    //泛型接口,将泛型定义在接口上
    interface Inter<T>{
        public void show(T t);
    }
     
    class InterImpl1 implements Inter<String>{
        public void show(String str){
            System.out.println("show:"+str);
        }
    }
    
    class InterImpl2 <Q> implements Inter<Q>{
        public void show(Q q){
            System.out.println("show:"+q);
        }
    }
    
    


    泛型的通配符:? 未知类型
    可以对类型进行限定  ? extends E:接收E类型或者子类型对象,上限
                             ?  super E:接收E类型或者E的福类型,下限
    一般来说,在存储元素的时候使用上限,因为这样都是按照上限类型来运算的,不会出现类型安全隐患。

    class TreeSet<E>
    {
         Tree(Comparator<? super E> comp);
    }
    什么时候使用下限?通常对集合中的元素进行取出操作时,可以使用下限。

    上限体现:
     

    package cn.ticast.p5.generic.advance.demo;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    import cn.itcast.p2.bean.Person;
    import cn.itcast.p2.bean.Student;
    import cn.itcast.p2.bean.Worker;
    
    public class GenericAdvanceDemo3 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            ArrayList<Person> al1 = new ArrayList<Person>();
    
            al1.add(new Person("abc", 30));
            al1.add(new Person("hehe", 34));
    
            ArrayList<Student> al2 = new ArrayList<Student>();
            al2.add(new Student("stu1", 11));
            al2.add(new Student("stu2", 22));
    
            ArrayList<Worker> al3 = new ArrayList<Worker>();
            al3.add(new Worker("stu1", 11));
            al3.add(new Worker("stu2", 22));
    
            ArrayList<String> al4=new ArrayList<String>();
    
            al4.add("abcdefg");
    //        al1.addAll(al4);//有泛型限定之后,al4不能添加到al1(类型不匹配,此处只能是Person及其子类);如果没有泛型限定,能够传入,但是有安全隐患,取出时会出错
            al1.addAll(al2);//有泛型限定之后,能够添加。Student是Person的子类
            al1.addAll(al3);
            
    //        printCollection(al);
    //        printCollection(al2);
    
        }
        
    /*
     * 一般在存储元素的时候使用上限,以为这样都是按照上限类型来运算的,不会出现类型安全隐患
     */
    class MyCollection<E>{
        public void add(E e){
            
        }
        public void addAll(MyCollection<? extends E> al){
            
        }
    }    
    }
    
    

    下限体现:

    package cn.ticast.p5.generic.advance.demo;
    
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    import cn.itcast.p2.bean.Person;
    import cn.itcast.p2.bean.Student;
    import cn.itcast.p2.bean.Worker;
    
    public class GenericAdvanceDemo4 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            TreeSet<Person> al1 = new TreeSet<Person>(new CompByName());
    
            al1.add(new Person("abc4", 30));
            al1.add(new Person("abc1", 34));
            al1.add(new Person("abc2", 38));
    
            TreeSet<Student> al2 = new TreeSet<Student>(new CompByStName());
            al2.add(new Student("stu1", 11));
            al2.add(new Student("stu7", 20));
            al2.add(new Student("stu2", 22));
    
            TreeSet<Worker> al3 = new TreeSet<Worker>();
            al3.add(new Worker("stu1", 11));
            al3.add(new Worker("stu2", 22));
    
            TreeSet<String> al4=new TreeSet<String>();
    
            al4.add("abcdefg");
    //        al1.addAll(al4);
            
    //        al1.addAll(al2);
    //        al1.addAll(al3);
    
    //        System.out.println(al1.size());
            
            Iterator<Student> it=al2.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
        }
        
        
    }
    
    /*
     * class TreeSet<E>
     * {Tree(Comparator<? super E> comp);}
     * 
     * 什么时候使用下限?通常对集合中的元素进行取出操作时,可以使用下限。
     */
    class CompByName implements Comparator<Person>{
    
        @Override
        public int compare(Person o1, Person o2) {
            int temp=o1.getName().compareTo(o2.getName());
            return temp==0?o1.getAge()-o2.getAge():temp;
        }
        
    }
    
    class CompByStName implements Comparator<Student>{
    
        @Override
        public int compare(Student o1, Student o2) {
            int temp=o1.getName().compareTo(o2.getName());
            return temp==0?o1.getAge()-o2.getAge():temp;
        }
        
    }
    
    

    通配符应用:

    package cn.ticast.p5.generic.advance.demo;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    import cn.itcast.p2.bean.Person;
    
    public class GenericAdvanceDemo5 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            ArrayList<Person> al1 = new ArrayList<Person>();
            al1.add(new Person("abc", 30));
            al1.add(new Person("abc4", 34));
            
            ArrayList<Person> al2 = new ArrayList<Person>();
            al2.add(new Person("abc22222", 30));
            al2.add(new Person("abc422222", 34));
            
            al1.containsAll(al2);
    
            ArrayList<String> al4 = new ArrayList<String>();
            al4.add("abcdefg");
            al4.add("abc");
            al1.containsAll(al4);
    
            Iterator<Person> it = al1.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    
        public static void printCollection(Collection<?> al) {
            Iterator<?> it = al.iterator();// Collection<? extends
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }
    
    class MyCollection2<E>{
        public boolean containsAll(Collection<?> coll){
            
            return true;
        }
    }
    
    

    集合查阅技巧:
    是否需要唯一?
    需要:Set
        是否需要指定顺序?
            需要:TreeSet
            不需要:HashSet
            想要一个和存储一致的顺序(有序):LinkedHashSet
    不需要:List
        是否需要频繁增删?
            需要:LinkedList
            不需要:ArrayList

    如何记住每个容器的结构和所属体系?
    看名字:
    List
        |--ArrayList
        |--LinkedList

    Set
        |--HashSet
        |--TreeSet

    后缀名就是该集合所属的体系。

    前缀名就是该集合的数据结构。
    array,数组,查询速度快,有脚标;
    link,链表,增删速度快,add、get、remove、first last方法;
    hash,哈希表,唯一性,元素需要覆盖hashCode方法和equals方法;
    tree,二叉树,排序,两个接口Comparable、Comparator;

    而且通常这些常用的结合容器都是不同步的。


    Map:一次添加一对元素,Collection一次添加一个元素。
    Map也称为双列集合,Collection称为单列集合。
    特点:
    -Map集合中存储的是键值对。
    -Map集合中必须保证键的唯一性。

    常用方法:
    1.添加
    value put(K key, V value); //返回上一个与key关联的值,如果没有则返回null。
    2.删除
    void clear();//清空map集合
    value remove(Object key); //根据指定的key,删除这个键值对
    3.判断
    boolean containsKey(key);//如果此映射包含指定键的映射关系,则返回 true。
    boolean containsValue(key);//如果此映射将一个或多个键映射到指定值,则返回 true。
    boolean isEmpty();//如果此映射未包含键-值映射关系,则返回 true。
    4.获取
    value get(Object key); //通过键获取值,如果没有该键则返回null;可以通过返回null,来判断是否包含指定键。
    int size();//获取键值对的个数。
    Set<K> keySet();// 返回此映射中包含的键的 Set 视图。

    Set<Map.Entry<K,V>> entrySet();//返回此映射中包含的映射关系的 Set 视图。

    public static interface Map.Entry<K,V>映射项(键-值对)。
    Map.entrySet 方法返回映射的 collection 视图,其中的元素属于此类。

    Collection<V> values();//返回此映射中包含的值的 Collection 视图。

    Map常见方法示例:

    package cn.ticast.p6.map.demo;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    public class MapDemo {
        public static void main(String[] args) {
            Map<Integer, String> map = new HashMap<Integer, String>();
            // method(map);
            method_2(map);
    
        }
    
        public static void method_2(Map<Integer, String> map) {
            map.put(8, "wangwu");
            map.put(2, "zhaoliu");
            map.put(7, "xiaoqiang");
            map.put(6, "wangcai");
    
            //只要姓名,不要键
            Collection<String> values = map.values();
            Iterator<String> it3 = values.iterator();
            while (it3.hasNext()) {
                System.out.println(it3.next());
            }
    
            /*
             * 第二种 通过Map转成Set就可以迭代 找到了另一个方法:entrySet
             * 该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型
             */
            Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
            Iterator<Map.Entry<Integer, String>> it2 = entrySet.iterator();
            while (it2.hasNext()) {
                Map.Entry<Integer, String> me = it2.next();
                Integer key = me.getKey();
                String value = me.getValue();
                System.out.println(key + ":" + value);
            }
    
            /*
             * 第一种 取出map中的所有元素 原理:先通过keySet方法,获取map中所有的键所在的Set集合,再通过Set的迭代器,
             * 获取到每一个键,从而用map的get方法获取每个键对应的值
             */
    
            // Set<Integer> keySet = map.keySet();
            // Iterator<Integer> it1 = keySet.iterator();
            // while (it1.hasNext()) {
            // Integer key = it1.next();// 通过迭代器获取每个键
            // String value = map.get(key);// 使用get方法,通过每个键获取对应的值
            // System.out.println(key + ":" + value);
            // }
    
        }
    
        public static void method(Map<Integer, String> map) {// 序号和姓名
            // 添加元素
            System.out.println(map.put(8, "wangcai"));// null
            System.out.println(map.put(8, "xiaoqiang"));// wangcai,存相同键,值会覆盖
            map.put(2, "zhangsan");
            map.put(7, "zhaoliu");
    
            // 删除
            // System.out.println("remove:"+map.remove(2));
    
            // 判断
            System.out.println("contains key:" + map.containsKey(7));
    
            // 获取
            System.out.println("get:" + map.get(8));
            System.out.println(map);
        }
    }
    
    

    Map常用的子类对象:
        |--HashTable    :内部结构是哈希表,是同步的。不允许null作为键和值※
            |--Properties:用来存储简直对型的配置文件的信息。可以和IO技术相结合、
        |--HashMap    :内部结构是哈希表,不是同步的。允许null作为键和值※
        |--TreeMap    :内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。

    HashMap应用示例:

    package cn.ticast.p6.hashmap.demo;
    
    import java.util.HashMap;
    import java.util.Iterator;
    
    import cn.itcast.p2.bean.Student;
    
    public class HashMapDemo {
    
        public static void main(String[] args) {
            /*
             * 将学生对象和学生的归属地,通过键与值存储到map集合中
             */
    
            HashMap<Student, String> hm = new HashMap<Student, String>();
            hm.put(new Student("lisi", 38), "北京");
            hm.put(new Student("zhaoliu", 24), "上海");
            hm.put(new Student("xiaoqiang",31), "沈阳");
            hm.put(new Student("wangcai", 28), "大连");
            hm.put(new Student("zhaoliu", 24), "铁岭");
    
            Iterator<Student> it = hm.keySet().iterator();
    
            while (it.hasNext()) {
                Student key = it.next();
                String value = hm.get(key);
                System.out.println(key.getName() + ":" + key.getAge() + "----"
                        + value);
            }
        }
    }
    
    

    TreeMap应用示例:

    package cn.ticast.p8.treemap.demo;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.TreeMap;
    
    import cn.itcast.p2.bean.Student;
    import cn.ticast.p3.comparator.ComparatorByName;
    
    public class TreeMapDemo {
    
        public static void main(String[] args) {
            /*
             * 将学生对象和学生的归属地,通过键与值存储到map集合中
             * 使用比较器Comparator,按姓名排序
             */
    
            TreeMap<Student, String> tm = new TreeMap<Student, String>(new ComparatorByName());
            tm.put(new Student("lisi", 38), "北京");
            tm.put(new Student("zhaoliu", 24), "上海");
            tm.put(new Student("xiaoqiang", 31), "沈阳");
            tm.put(new Student("wangcai", 28), "大连");
            tm.put(new Student("zhaoliu", 24), "铁岭");
    
            Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();
    
            while (it.hasNext()) {
                Map.Entry<Student, String> me = it.next();
                Student key = me.getKey();
                String value = me.getValue();
                System.out.println(key.getName() + ":" + key.getAge() + "----"
                        + value);
            }
        }
    }
    package cn.ticast.p3.comparator;
    
    import java.util.Comparator;
    
    import cn.itcast.p2.bean.Person;
    
    public class ComparatorByName/*extends Object*/ implements Comparator<Person> {
    
        @Override
        public int compare(Person o1, Person o2) {
            int temp=o1.getName().compareTo(o2.getName());
            return temp==0?o1.getAge()-o2.getAge():temp;
        }
    }
    
    

    LinkedHashMap:使用LinkedHashMap,则有序(存取顺序相同)
    LinkedHashMap应用示例:

    package cn.itcast.p1.map.demo;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class LinkedHashmapDemo {
        public static void main(String[] args) {
            HashMap<Integer, String> hm = new LinkedHashMap<Integer, String>();
    
            hm.put(7, "zhouqi");
            hm.put(3, "zhangsan");
            hm.put(1, "qianyi");
            hm.put(5, "wangwu");
    
            Iterator<Map.Entry<Integer, String>> it = hm.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Integer, String> me = it.next();
                Integer key = me.getKey();
                String value = me.getValue();
                System.out.println(key + ":" + value);
            }
        }
    }
    
    

    Map集合练习:

    package cn.itcast.p1.map.test;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.TreeMap;
    
    /*
     * 练习:
     * "fdqavchsacdfs"获取该字符串中,每一个字母出现的次数。
     * 要求打印的结果是a{2}b{1}...;
     * 思路:
     * 对于结果的分析发现,字母和次数之间存在着映射的关系,而且这种关系很多
     * 所以需要存储,能存储映射关系的容器有数组和Map结合
     * 关系一方是否是有序编号?否
     * 那就使用Map集合。又发现可以保证唯一性的一方具备着顺序,如a、b、c……
     * 所以可以使用TreeMap集合。
     * 
     * 这个集合中,最终应该存储的是字母和次数的对应关系
     * 1.因为操作的是字符串中的字母,所以先将字符串变为字符数组;
     * 2.遍历字符数组,用每一个字母作为键去查Map集合这个表;
     *      如果该字母键不存在,则将该字母作为键,1作为值存储到Map集合中;
     *      如果该字母键存在,则将该字母对应的值取出,并自增,再将该字母和+1后的值存储到Map集合中;
     *      键相同,值会覆盖。这样,就记录住了该字母的次数;
     * 3.遍历结束,Map集合中就记录了所有字母出现的次数。
     */
    public class MapTest {
        public static void main(String[] args) {
            String str = "fd++qa--vc   hsacdfs";
    
            String s = getCahrCount(str);
    
            System.out.println(s);
        }
    
        public static String getCahrCount(String str) {
            // 将字符串变成字符数组
            char[] chs = str.toCharArray();
    
            // 定义Map集合表
            Map<Character, Integer> map = new TreeMap<Character, Integer>();
    
            // 遍历
            for (int i = 0; i < chs.length; i++) {
                if(!(chs[i]>='a'&&chs[i]<='z'||chs[i]>='A'&&chs[i]<='Z'))
                    continue;
                // 将数组中的数组作为键去查Map表
                Integer value = map.get(chs[i]);
                // 判断值是否为null
                int count = 1;
                if (value != null) {
                    count = value + 1;
                }
                map.put(chs[i], count);
    
                /*
                 * if(value==null){ map.put(chs[i], 1); }else{ map.put(chs[i],
                 * value+1); }
                 */
            }
            return mapToString(map);
        }
    
        private static String mapToString(Map<Character, Integer> map) {
            StringBuilder sb=new StringBuilder();
        
            Iterator<Character> it=map.keySet().iterator();
            while(it.hasNext()){
                Character key=it.next();
                Integer value=map.get(key);
                
                sb.append(key+"{"+value+"}");
            }
            return sb.toString();
        }
    }
    
    
    package cn.itcast.p1.map.test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class MapTest2 {
        public static void main(String[] args) {
            /*
             * Map在有映射关系时,可以优先考虑
             * 
             * 在查表法中的应用较为多见
             */
    
            String week = getWeek(1);
            System.out.println(week);
            
            System.out.println(getWeekByMap(week));
        }
    
        public static String getWeekByMap(String week) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("星期一","Mon");
            map.put("星期二","Tus");
            map.put("星期三","Wes");
            map.put("星期日","Sun");
            map.put("星期天","Sun");
            return map.get(week);
        }
    
        public static String getWeek(int week) {
            if (week < 1 || week > 7)
                throw new RuntimeException("没有对应的星期,请重新输入");
            String[] weeks = { "", "星期一", "星期二" };
    
            return weeks[week];
        }
    }
    
    


    Collections工具类
    Collections是集合框架的工具类,里边的方法都是静态的。

    static <T extends Comparable<? super T>> void  sort(List<T> list)
    根据元素的自然顺序 对指定列表按升序进行排序。

    static <T> int  binarySearch(List<? extends Comparable<? super T>> list, T key)
    使用二分搜索法搜索指定列表,以获得指定对象。
    使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过 sort(List) 方法)。如果没有对列表进行排序,则结果是不确定的。如果列表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
    如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。

    static <T extends Object & Comparable<? super T>> T  max(Collection<? extends T> coll)
    根据元素的自然顺序,返回给定 collection 的最大元素。

    static <T> Comparator<T>  reverseOrder()          
    返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。

    static void reverse(List<?> list)
    反转指定列表中元素的顺序。

    static <T> boolean  replaceAll(List<T> list, T oldVal, T newVal)
    使用另一个值替换列表中出现的所有某一指定值。

    static <T> void  fill(List<? super T> list, T obj)
    使用指定元素替换指定列表中的所有元素。

    static void shuffle(List<?> list)
    使用默认随机源对指定列表进行置换。

    static <T> Enumeration<T>  enumeration(Collection<T> c)
    返回一个指定 collection 上的枚举。


    给非同步的集合加锁
    List list=new ArrayList();//非同步的
    list=MyCollections.Synchronized(list);//返回一个同步的list

    class MyCollections{
    
        public static List synchronized(List list){
            return new MyList(list);
        }
    
    }
    private class MyList implements List{
        private List list;
        pirvate static final Object lock=new Object();
        MyList(List list){
            this.list=list;
        }
    
        public boolean add(Object obj){
            synchronized(lock)
                {
                    return list.add(obj);
                }
        }
    
    public boolean remove(Object obj){
            synchronized(lock)
                {
                return list.remove(obj);
                }
        }
    }
    
    

    static <T> Collection<T>  synchronizedCollection(Collection<T> c)
    返回指定 collection 支持的同步(线程安全的)collection。
    static <T> List<T>  synchronizedList(List<T> list)
    返回指定列表支持的同步(线程安全的)列表。
    static <K,V> Map<K,V>  synchronizedMap(Map<K,V> m)
    返回由指定映射支持的同步(线程安全的)映射。
    static <T> Set<T>  synchronizedSet(Set<T> s)
    返回指定 set 支持的同步(线程安全的)set。
    static <K,V> SortedMap<K,V>  synchronizedSortedMap(SortedMap<K,V> m)
    返回指定有序映射支持的同步(线程安全的)有序映射。
    static <T> SortedSet<T>  synchronizedSortedSet(SortedSet<T> s)
    返回指定有序 set 支持的同步(线程安全的)有序 set。


    Arrays工具类
    Arrays集合框架的工具类,里面的方法都是静态的。

    重点: List asList(数组) 将数组转成集合
    好处:可以使用结合的方法操作数组中的元素
    注意:数组的长度是固定的,所以对于集合的增删方法是不可以使用的,
    否则会发生UnsupportedOperationException。

    如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
    如果数组中的元素是基本类型数值,那么会将数组作为集合中的元素进行存储。

    package cn.itcast.p3.toolclass.arrays.demo;
    
    import java.util.Arrays;
    import java.util.List;
    
    //数组转成集合
    public class ArraysDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
    
            // int[] arr={3,1,5,6,3,6};
            // System.out.println(Arrays.toString(arr));
    
            System.out.println("demo_1");
            demo_1();
            System.out.println("demo_2");
            demo_2();
        }
    
        public static void demo_2() {
            /*
             * 如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
             * 如果数组中的元素是基本类型数值,那么会将数组作为集合中的元素进行存储。
             */
            int[] arr = { 31, 11, 51, 61 };
    
            List<int[]> list = Arrays.asList(arr);
    
            System.out.println(list);
        }
    
        /**
         * 
         */
        private static void demo_1() {
            String[] arr = { "abc", "haha", "xixi" };
            boolean b = myContains(arr, "xixi");
            System.out.println("contains:" + b);
    
            List<String> list = Arrays.asList(arr);
            // list.add("hehe");//数组的长度是固定的,所以对于集合的增删方法是不可以使用的,
            // 否则会发生UnsupportedOperationException。
            boolean b1 = myContains(arr, "xixi");
            System.out.println("list contains:" + b1);
            System.out.println(list);
        }
    
        public static boolean myContains(String[] arr, String key) {
            for (int i = 0; i < arr.length; i++) {
                if (arr[i].equals(key))
                    return true;
            }
            return false;
        }
    
        // toString的经典实现
        public static String myToString(int[] a) {
            int iMax = a.length - 1;
            if (iMax == -1)
                return "[]";
    
            StringBuilder b = new StringBuilder();
            b.append('[');
            for (int i = 0;; i++) {// 中间省略条件判断,提高效率
                b.append(a[i]);
                if (i == iMax)
                    return b.append(']').toString();
                b.append(", ");
            }
        }
    }
    
    


    集合转成数组
    使用的是Collection接口中的toArray方法。
    集合转成数组,可以对集合中的元素操作的方法进行限定,不允许对其进行增删。

    toArray方法需要传入一个指定类型的数组
    长度的定义方法:
    如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组;
    如果长度大于集合的size,该方法就会使用指定的数组村粗集合中的元素,其他位置默
    为null;
    建议数组长度是指定的结合的size

    package cn.itcast.p3.toolclass.arrays.demo;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class ToArray {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            /*
             * 集合转成数组
             */
            List<String> list=new ArrayList<String>();
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
            
            /*
             * toArray方法需要传入一个指定类型的数组
             * 长度的定义方法:
             * 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组;
             * 如果长度大于集合的size,该方法就会使用指定的数组村粗集合中的元素,其他位置默认为null;
             * 建议数组长度是指定的结合的size
             */
            String[] arr=list.toArray(new String[2]);
            
            System.out.println(Arrays.toString(arr));
        }
    
    }
    
    

    foreach循环
    格式:
    for(类型 变量 : Collection集合 | 数组)
    {
       
    }

    传统for循环和高级for的区别:
    传统for可以完成对语句执行多次,因为可以定义控制循环的增量和条件;
    而高级for是只用简化形式,它必须有被遍历的目标,该目标要么是数组,要么是Collection集合;
    对于数组的遍历,如果仅仅是获取数组中的元素,可以使用高级for;如果要对数组的脚标进行操作,建议使用传统for。

    package cn.itcast.p4.news.demo;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class ForEachDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
    
            List<String> list = new ArrayList<String>();
    
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
    
            for (String s : list) {// 简化书写
                System.out.println(s);
            }
    
            int[] arr = { 3, 1, 5, 6, 7, 2 };
            for (int i : arr) {
                System.out.println(i);
            }
    
            // 可以使用高级for遍历map集合:不能直接作用,但是可以将map转成单列的set,就可以使用
            Map<Integer,String> map=new HashMap<Integer,String>();
            
            map.put(3, "zhagsan");
            map.put(1, "wangyi");
            map.put(7, "wangwu");
            map.put(4, "zhangsan");
            
            for(Integer key:map.keySet()){
                String value=map.get(key);
                System.out.println(key+":"+value);
            }
            for(Map.Entry<Integer, String> me:map.entrySet()){
                Integer key=me.getKey();
                String value=me.getValue();
                System.out.println(key+":"+value);
            }
            
            // Iterator<String> it=list.iterator();
            // while(it.hasNext()){
            // System.out.println(it.next());
            // }
        }
    }
    
    

    函数可变参数
    其实就是一个数组,但是接受的是数组中的元素,自动将这些元素封装成数组,简化了调用者的书写。
    ※注意事项:可变参数类型,必须定义在参数列表的结尾。

    package cn.itcast.p4.news.demo;
    
    public class ParamterDemo {
        public static void main(String[] args) {
            int[] arr = { 5, 1, 4, 7, 3 };
            int sum1 = add(arr);
            System.out.println("sum1=" + sum1);
    
            int sum2 = newAdd(5, 1, 4, 7, 3);
            System.out.println("sum2=" + sum2);
            int sum3 = newAdd(5, 1, 2, 7, 9, 8, 7, 6);
            System.out.println("sum3=" + sum3);
        }
    
        public static int newAdd(int a,int... arr) {// 可变参数
            int sum = 0;
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
            return sum;
        }
    
        public static int add(int[] arr) {
            int sum = 0;
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
            return sum;
        }
    }
    
    

    静态导入

    package cn.itcast.p4.news.demo;
    
    //import static java.util.Collections.sort;//其实导入的是类中的静态成员
    //import static java.util.Collections.max;
    import static java.lang.System.out;
    import static java.util.Collections.max;
    import static java.util.Collections.sort;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class StaticImportDemo {
        public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
    
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
    
            out.println(list);
    
            // Collections.sort(list);
            sort(list);
    
            out.println(list);
    
            // String max = Collections.max(list);
            String max = max(list);
            out.println("max=" + max);
        }
    
    }
    
    

    其他对象API
    System类
    public final class Systemextends Object
    System 类包含一些有用的类字段和方法。它不能被实例化。
    System类中的方法和属性都是静态的。

    static long currentTimeMillis(); //返回以毫秒为单位的当前时间。
    static String getProperty(String key, String def)
    获取用指定键描述的系统属性。
    Object setProperty(String key, String value)
    调用 Hashtable 的方法 put。

    package cn.itcast.p1.otherapi.demo;
    
    import java.util.Properties;
    import java.util.Set;
    
    public class SystemDemo {
    
        private static final String SPACE_SEPARATOR = System
                .getProperty("line.separator");
    
        /**
         * @param args
         */
        public static void main(String[] args) {
    
            System.out.println("Hello" + SPACE_SEPARATOR + " World");// 能实现任何系统中的换行
            // demo_0();
            // demo_1();
            
            //给系统设置属性信息,这些信息是全局的,其他程序都可以使用
            System.setProperty("myclasspath", "c:\\myclass");
            
        }
    
        public static void demo_1() {
            // 获取系统的徐行信息,并存储到了Properties集合中
            /*
             * Properties集合中存储的都是String类型的键和值 最好使用它自己的存储和取出的方法来完成元素的操作
             */
            Properties prop = System.getProperties();
    
            Set<String> nameSet = prop.stringPropertyNames();
    
            for (String name : nameSet) {
                String value = prop.getProperty(name);
                System.out.println(name + "::" + value);
            }
    
        }
    
        private static void demo_0() {
            long l1 = System.currentTimeMillis();
            System.out.println(l1);
            // System.out.println(l1/1000/60/60/24/365);
    
            long temp = 1344227567838l;
    
            long l2 = System.currentTimeMillis();
            System.out.println(l2 - temp);
        }
    }
    
    

    public class Runtimeextends
    Object每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
    应用程序不能创建自己的 Runtime 类实例。

    Runtime没有构建方法摘要,说明该类不能创建对象。
    又发现,Runtime有非静态的方法,说明该类应该提供静态的返回该类对象的方法。
    而且只有一个,说明Runtime类使用了单例设计模式完成。※

    package cn.itcast.p1.otherapi.demo;
    
    import java.io.IOException;
    
    public class RuntimeDemo {
    
        /**
         * @param args
         * @throws IOException 
         * @throws InterruptedException 
         */
        public static void main(String[] args) throws IOException, InterruptedException {
            Runtime r=Runtime.getRuntime();
            Process p=r.exec("notepad.exe");
            Thread.sleep(5000);
            p.destroy();
        }
    }
    
    

    Math
    public final class Mathextends ObjectMath
    类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。

    常用的方法:
    ceil();//返回大于参数的最小整数
    floor();//返回小于参数的最大整数
    round();//返回四舍五入后的整数
    pow(a,b);//返回a的b次方
    random();
    //返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。

    package cn.itcast.p1.otherapi.demo;
    
    import java.util.Random;
    
    public class MathDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // double d1 = Math.ceil(12.56);
            // double d2 = Math.floor(12.56);
            // double d3 = Math.round(12.56);
            //
            // System.out.println("d1=" + d1);
            // System.out.println("d2=" + d2);
            // System.out.println("d3=" + d3);
            //
            // double d = Math.pow(10, 2);
            // System.out.println("d=" + d);
            Random r = new Random();
            for (int i = 0; i < 10; i++) {
                // double d = Math.ceil(Math.random()*100);
                
                // double d = (int) (r.nextDouble() * 6 + 1);
                int d = r.nextInt(6) + 1;
                System.out.println(d);
            }
        }
    }
    
    


    Date类
    public class Dateextends Objectimplements Serializable, Cloneable, Comparable<Date>

    年份 y 由整数 y - 1900 表示。
    月份由从 0 至 11 的整数表示;0 是一月、1 是二月等等;因此 11 是十二月。
    日期(一月中的某天)按通常方式由整数 1 至 31 表示。
    小时由从 0 至 23 的整数表示。因此,从午夜到 1 a.m. 的时间是 0 点,从中午到 1 p.m. 的时间是 12 点。
    分钟按通常方式由 0 至 59 的整数表示。
    秒由 0 至 61 的整数表示;值 60 和 61 只对闰秒发生,尽管那样,也只用在实际正确跟踪闰秒的 Java 实现中。于按当前引入闰秒的方式,两个闰秒在同一分钟内发生是极不可能的,但此规范遵循 ISO C 的日期和时间约定。

    日期对象和毫秒值之间的转换

    毫秒值-->日期对象:
    1.通过Date对象的构造方法完成 new Date(timeMilis);
    2.通过setTime()设置;
    目的:可以通过Date对象的方法对该日期中的各个字段(年月日等)进行操作;
    日期对象-->毫秒值
    getTime();
    目的:可以通过具体的数值进行运算;

    boolean after(Date when)
    测试此日期是否在指定日期之后。

    boolean before(Date when)
    测试此日期是否在指定日期之前。

    boolean equals(Object obj)
    比较两个日期的相等性。

    int compareTo(Date anotherDate)
    比较两个日期的顺序。

    String toString()
    把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

    对日期对象进行格式化
    static DateFormat getDateTimeInstance(int dateStyle, int timeStyle)
    获取日期/时间格式器,该格式器具有默认语言环境的给定日期和时间格式化风格。

    package cn.itcast.p1.otherapi;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class DateDemo {
    
        /**
         * @param args
         * @throws ParseException
         */
        public static void main(String[] args) throws ParseException {
    
            // methodDemo_1();
            // methodDemo_2();
            methodDemo_3();
    
        }
    
        /**
         * 日期格式的字符串-->日期对象,使用的是DateFormat类中的parse方法
         * @throws ParseException
         */
        public static void methodDemo_3() throws ParseException {
            String str_date = "2012年4月19日";
            str_date = "2011---8---17";
    
            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
            // 只能解析默认风格的日期,如2012-8-17
            // DateFormat dateFormat = DateFormat.getDateInstance();//
            dateFormat = new SimpleDateFormat("yyyy---MM---dd");// 自定义风格
    
            Date d = dateFormat.parse(str_date);
            System.out.println(d);
        }
    
        /**
         * 对日期对象进行格式化 日期对象-->日期格式的字符串,使用的是DateFormat类中的format方法
         */
        public static void methodDemo_2() {
            Date date = new Date();
    
            // 获取日期格式对向,具备着默认风格。FULL、LONG等可以指定风格
            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);
            dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
                    DateFormat.LONG);
    
            // 如果风格是自定义的,如何解决
            dateFormat = new SimpleDateFormat("yyyy--MM--dd");
    
            String str_date = dateFormat.format(date);
            System.out.println(str_date);
        }
    
        private static void methodDemo_1() {
            long time = System.currentTimeMillis();
            System.out.println(time);// 1344324000837
    
            Date date = new Date();// 将当前日期和时间封装成对象
            System.out.println(date);// Tue Aug 07 15:17:40 CST 2012
    
            Date date2 = new Date(1344324000837l);// 将制定毫秒值封装成对象
            System.out.println(date2);
        }
    }
    
    

    Date练习示例:

    package cn.itcast.p1.otherapi.test;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.util.Date;
    
    /*
     * "2012-3-17"到"2012-4-6"
     * 中间有多少天
     * 思路:
     * 两个日期相减。
     * 必须要有两个可以进行减法运算的数。
     * 能相减的可以是毫秒值。使用Date对象获取毫秒值。
     * 从日期格式字符串获取时间。将字符串转成Date对象。
     * 
     * 1.将日期格式的字符串转成对象;
     * 2.将Date对象转成毫秒值;
     * 3.毫秒值相减,然后转换成天数。
     */
    public class DateTest {
    
        /**
         * @param args
         * @throws ParseException
         */
        public static void main(String[] args) throws ParseException {
    
            String str_date1 = "2012-3-17";
            String str_date2 = "2012-4-6";
            test(str_date1, str_date2);
    
        }
    
        public static void test(String str_date1, String str_date2)
                throws ParseException {
    
            // 1.将日期字符串转成日期对象
            // 定义日期格式对象
            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
            // dateFormat=new SimpleDateFormat("yyyy-MM-dd");
    
            //2.将Date对象转换成毫秒值
            Date date1 = dateFormat.parse(str_date1);
            Date date2 = dateFormat.parse(str_date2);
            long time1 = date1.getTime();
            long time2 = date2.getTime();
    
            //3.毫秒值相减,然后转换成天数
            long time = Math.abs(time1 - time2);
            int day = getDay(time);
            System.out.println(day);
    
        }
    
        public static int getDay(long time) {
            return (int) (time / 1000 / 60 / 60 / 24);
        }
    
    }
    
    

    Calendar类

    package cn.itcast.p1.otherapi;
    
    import java.util.Calendar;
    
    public class CalendarDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
    
            Calendar c = Calendar.getInstance();
    
            int year = 2012;
            showDays(year);
    
        }
    
        /**
         * @param c
         */
        private static void showDays(int year) {
            Calendar c = Calendar.getInstance();
            c.set(year, 2, 1);
            c.add(Calendar.DAY_OF_MONTH, -1);
            showDate(c);
        }
    
        /**
         * Calendar c = Calendar.getInstance();
         */
        private static void showDate(Calendar c) {
    
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH) + 1;
            int day = c.get(Calendar.DAY_OF_MONTH);
            int week = c.get(Calendar.DAY_OF_WEEK);
    
            System.out.println(year + "年" + month + "月" + day + "日 "
                    + getWeek(week));
        }
    
        public static String getWeek(int i) {
            String[] weeks = { "", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
    
            return weeks[i];
        }
    
    }
    
  • 相关阅读:
    web.xml配置文件详解
    spring MVC配置文件详解
    路由导航刷新后导致当前选中的导航样式不见的解决办法
    vue input 使用v-model想要改变父属性的写法
    JS 编写一个指定范围内的随机数返回方法
    vue-router 3.1.5报错:vue-router.esm.js?8c4f:2089 Uncaught (in promise)
    Failed to mount component: template or render function not defined. vue
    vscode 操作debugger for chrome的配置文件写法
    JS操作DOM方法总结
    npm 代理配置的方法
  • 原文地址:https://www.cnblogs.com/chenchong/p/2627188.html
Copyright © 2020-2023  润新知