单列集合 & 双列集合 & 泛型类 &正则表达式

首先我们先提出两个问题:

数组的回顾

  • 数组: 存储同一种数据类型的集合容器
  • 数组的特点:
    1. 只能存储同一种数据类型的数据
    2. 一旦初始化, 长度固定
    3. 数组中的元素与元素之间的内存地址是连续的
  • 注意: Object类型的数组可以存储任意类型的数据(Object[])

public class Demo {
    public static void main(String[] args) {
        Object[] arr = new Object[10];
        arr[1] = "abc";
        arr[2] = 'a';
        arr[3]  = 12;
    }   
}
  • 什么是泛型?
  • 为什么要使用泛型?
    我们先来看看第一个问题什么是泛型。如果你对Java三大特性中的多态性理解的比较透彻的话,泛型就比较好理解了。多态性表示一个对象具备多种状态。比如说你自己,你首先是一个人,同时你在看这篇帖子说明你是一个程序员,下了班之后你可能有变成了禽兽。所以你具备这人形态,程序员形态,和兽形态,这就是多态,一种事物具备多种状态!而泛型就更加纯粹的多态,他可以是任何一种形态,俗称变态(开个玩笑o(∩_∩)o)。泛型的意思就是可以表示任何一种形态,任何一种数据类型。这就好像情人节你女朋友送你的礼物一样,你先拿到的是一个礼物包装盒,而盒子里面可能是一个钱包,也可能是一个高档打火机,还有可能是一坨屎!盒子里面有可能是任何一种事物,你对此完全不知道,你知道你会收到这样一份礼物,而礼物具体是什么,你全然不知。

集合(Collection)

  • 集合:集合是存储对象数据的集合容器
  • 集合比数组的优势:
    1. 集合可以存储任意类型的对象数据,数组只能存储同一种数据类型的数据
    2. 集合的长度是会发生变化的,数组的长度是固定的
  • Collection(单例集合的跟接口)的子接口 (还有双例集合)
    • List: 如果是实现了List接口的集合类,具备的特点: 有序, 可重复
    • Set: 如果是实现了Set接口的集合类,具备特点: 无序, 不可重复
  • Collection接口中的方法:
    • 增加:
      • add(E e) 添加成功返回true,添加 失败返回false.
      • addAll(Collection c) 把一个集合 的元素添加到另外一个集合中去
    • 删除
      • clear()
      • remove(Object o)
      • removeAll(Collection c)
      • retainAll(Collection c)
    • 查看
      • size()
    • 判断
      • isEmpty()
      • contains(Object o)
      • containsAll(Collection<?> c)
    • 迭代
      • toArray()
      • iterator()

public class Demo {

   public static void main(String[] args) {
       Collection c = new ArrayList();
       c.add("令计划");
       c.add("徐才厚");
       c.add("周永康");
       System.out.println("添加成功吗?"+c.add("郭美美"));

       //创建集合
       Collection c2 = new ArrayList();
       c2.add("徐才厚");
       c2.add("郭美美");
       c2.add("狗娃");

       /*
       c.addAll(c2); // 把c2的元素的添加到c集合中去
       */

       /*
        删除方法:
       c.clear(); //clear()清空集合中的元素
       System.out.println("删除成功吗?"+c.remove("美美"));  // remove 指定集合中的元素删除,删除成功返回true,删除失败返回false

       c.removeAll(c2); //删除c集合中与c2的交集元素
       c.retainAll(c2); //保留c集合与c2的交集元素,其他的元素一并删除
       */
       System.out.println("查看元素个数:"+c.size());     
       System.out.println("集合的元素:"+ c);
   }
}
  • 集合中的判断方法:

    • isEmpty() : 判断集合是否为空元素
    • contains(Object o) : 判断集合中是否存在指定的元素
    • containsAll(Collection<?> c) :
      判断X集合中包是否包含X2集合中的所有元素
  • 集合的toArray()方法:

    Collection c = new ArrayList();
    c.add("令计划");
    c.add("徐才厚");
    c.add("周永康");
    Object[] arr = c.toArray(); //把集合中的元素全部存储到一个Object的数组中返

迭代器

  • 迭代器的作用:就是用于抓取集合中的元素
  • 迭代器的方法:
    1. hasNext() : 寻问是否有元素可遍历,
      如果有元素可以遍历返回true,否则返回false
    2. next() : 获取元素…
    3. remove() : 移除迭代器最后一次返回的元素
  • 使用迭代器的时候, 报出的异常代码 :
    NoSuchElementException(没有元素的异常)(出现的原因 :
    没有元素可以被迭代了)

public class Demo{

    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("狗娃");
        c.add("狗剩");
        c.add("铁蛋");
        c.add("美美");

        /*//遍历集合的元素------>方式一: 可以使用toArray方法。
        Object[] arr = c.toArray(); // toArray()  把集合 的元素存储到一个 Object的数组中 返回。
        for(int i = 0 ; i<arr.length ; i++){
            System.out.print(arr[i]+",");
        }

        //要求使用iterator迭代器遍历。
        */

        Iterator it = c.iterator();  //返回一个迭代器, 疑问:iterator()方法返回的是一个接口类型,为什么接口又可以调用方法可以使用呢?  iterator 实际上返回的是iterator接口的实现类对象
        /*
        while(it.hasNext()){ // hasNext() 问是否有元素可以遍历
            System.out.println("元素:"+ it.next()); //获取元素
        }
        */

        /*it.next();
        it.next();
        it.remove();  //删除迭代器最后一次返回的元素
*/

        //清空集合的元素
        while(it.hasNext()){
            it.next();
            it.remove();
        }
        System.out.println("集合的元素:"+ c);
    }   
}
 public class GrilFriend<T> {

    private T t;

    public void buyGift(T t) {
        this.t = t;
    }

    public T getGift() {
        return t;
    }

    public static void main(String[] args) {
        GrilFriend<Shit> myGrilFriend = new GrilFriend<Shit>();
        myGrilFriend.buyGift(new Shit("狗屎"));
        Shit gift = myGrilFriend.getGift();
        System.out.println(gift.name);
    }

}

class Shit {

    final String name;

    public Shit(String name) {
        this.name = name;
    }

}

集合的体系

Collection 单列集合的根接口

  1. List 如果实现了List接口的集合类,具备的特点:有序,可重复
  • ArrayList: 底层是维护了一个Object数组实现的, 特点 : 查询速度快,
    增删慢
    什么时候使用ArrayList: 如果目前的数据是查询比较多, 增删比较少的时候,
    那么就使用ArrayList存储这批数据(比如 : 高校的图书馆)
  • LinkedList : 底层是使用了链表数据结构实现的; 特点 :
    查询速度慢,增删快
  • Vector(了解即可)
  1. Set 如果是实现了Set接口的集合类,具备的特点 : 无序, 不可重复
  • HashSet 底层是使用了哈希表来支持的,特点: 存取速度快.
    • hashSet的实现原理:往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值,
      然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置
    • 情况1:
      如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上
    • 情况2:
      如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,
      那么该元素运行添加
  • TreeSet : 如果元素具备自然顺序的特性,
    那么就按照元素自然顺序的特性进行排序存储

这就是泛型,你永远不知道你女朋友会送你什么礼物,这里的礼物可能是任何一种类型(她可能会真的送你一坨屎)

集合子类的方法:

  • Linkedlist特有的方法:
    1:方法介绍
    addFirst(E e)
    addLast(E e)
    getFirst()
    getLast()
    removeFirst()
    removeLast()
    2:数据结构
    1:栈(1.6): 主要是用于实现堆栈数据结构的存储方式; 先进后出: push() ,
    pop()
    2:队列(双端队列1.5) :
    主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式;
    先进先出 : offer(), poll()
    3:返回逆序的迭代器对象 : descendingIterator() 返回逆序的迭代器对象

  • ArrayList 特有的方法:

    • ensureCapacity(int minCapaci上ty)
    • 澳门新葡亰3522平台游戏,trimToSize()
    • 笔试题目: 使用ArrayList无参的构造函数创建一个 对象时,
      默认的容量是多少? 如果长度不够使用时又自增增长多少?
      ArrayList底层是维护了一个Object数组实现
      的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍
  • treeSet添加自定义元素:

  • treeSet要注意的事项:

  1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。

  2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在compareTo(T
    o)方法上

  3. 如果比较元素的时候,compareTo方法返回
    的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)

  4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序
    的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器

  5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口,
    在创建TreeSet对象的时候也传入了比较器那么是以比较器的比较规则优先使用

    • 如何自定义定义比较器:
      自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可

  自定义比较器的格式 :
    class  类名  implements Comparator{               

    }

  推荐使用:使用比较器(Comparator)

class  Emp implements Comparable<Emp>{

    int id;
    String name;
    int salary;

    public Emp(int id, String name, int salary) {
        super();
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "{ 编号:"+  this.id+" 姓名:"+ this.name+" 薪水:"+ this.salary+"}";
    }

    //@Override //元素与元素之间的比较规则。
    // 负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。 
    public int compareTo(Emp o) {
//      System.out.println(this.name+"compare"+ e.name);
        return this.salary- o.salary;
    }   
}

//自定义一个比较器
class MyComparator implements Comparator<Emp>{

    @Override
    public int compare(Emp o1, Emp o2) {
        return o1.id-o2.id;
    }

    //根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。 
    /*@Override
    public int compare(Object o1, Object o2) {
        Emp e1 = (Emp) o1;
        Emp e2 = (Emp) o2;
        return e1.id - e2.id;
    }*/ 
}

public class Demo {

    public static void main(String[] args) {
        //创建一个比较器对象
        MyComparator comparator = new MyComparator();
        //创建TreeSet的时候传入比较器
        TreeSet tree = new TreeSet(comparator);

        tree.add(new Emp(110, "老陆", 100));
        tree.add(new Emp(113, "老钟", 200));
        tree.add(new Emp(220, "老汤", 300));
        tree.add(new Emp(120, "老蔡", 500));
        System.out.println("集合的元素:"+tree);      
    }
}
  • treeSet排序

需求:将字符串中的数值进行排序
public class Demo {

    public static void main(String[] args) {
        String str="8 10 15 5 2 7";
        String[] datas = str.split(" ");

        TreeSet tree = new TreeSet();
        for(int i = 0 ; i<datas.length ; i++){
            tree.add(Integer.parseInt( datas[i])); // 字符串转int类型数据是需要使用Integer.parseInt()
        }

        //遍历treeSet的元素拼接成对应的字符串
        Iterator it = tree.iterator();
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }   
    }
}

接下来我们来看我们为什么要使用泛型
,相信List集合容器,大家都用的滚瓜烂熟了,我们先来看下List的源码

双列集合

public interface List<E> extends Collection<E> {
    public boolean add(E object);
    public boolean addAll(Collection<? extends E> collection);
    public E get(int location);
}

Map接口(双列集合)

  • Map 如果是实现了Map接口的集合类,具备的特点:
    存储的数据都是以键值对的形式存在的,键不可重复,值可以重复
  • Map接口的方法:
  • 添加:
    put(K key, V value)
    putAll(Map<? extends K,? extends V> m)
  • 删除
    remove(Object key)
    clear()
  • 获取:
    get(Object key)
    size()
  • 判断:
    containsKey(Object key)
    containsValue(Object value)
    isEmpty()

public class Demo {

    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String, String>();
        //添加方法
        map.put("汪峰", "章子怡");
        map.put("文章", "马伊琍");
        map.put("谢霆锋","张柏芝");
        /*
        添加
        System.out.println("返回值:"+map.put("谢霆锋","黄菲"));  // 如果之前没有存在该键,那么返回的是null,如果之前就已经存在该键了,那么就返回该键之前对应 的值。
        Map<String,String> map2 = new HashMap<String, String>();
        map2.put("杨振宁", "翁帆");
        map2.put("习总", "彭丽媛");
        map.putAll(map2); // 把map2的元素添加到map集合中。

        */

        /*
        删除
        System.out.println("删除的数据是:"+map.remove("汪峰")) ;  //根据键删除一条map中的数据,返回的是该键对应 的值。
        map.clear(); //清空集合中的所有数据。
        */

        /* 获取
        System.out.println("根据指定 的键获取对应的值:"+ map.get("文章"));
        System.out.println("获取map集合键值对个数:"+map.size());

        判断
        System.out.println("判断map集合是否包含指定的键:"+ map.containsKey("文章"));
        System.out.println("判断map集合中是否包含指定 的值:"+ map.containsValue("张柏芝"));
        map.clear();
        System.out.println("判断map集合是否为空元素:"+ map.isEmpty());
        */
        System.out.println("集合的元素:"+ map);  
    }
}
  • Map迭代
    • keySet()
    • values()
    • entrySet()

public class Demo {

    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String, String>();
        //添加方法
        map.put("汪峰", "章子怡");
        map.put("文章", "马伊琍");
        map.put("谢霆锋","张柏芝");
        map.put("成龙", "林凤娇");
        /*
        //map集合中遍历方式一: 使用keySet方法进行遍历       缺点: keySet方法只是返回了所有的键,没有值。 
        Set<String> keys = map.keySet();  //keySet() 把Map集合中的所有键都保存到一个Set类型 的集合对象中返回。
        Iterator<String> it = keys.iterator();
        while(it.hasNext()){
            String key = it.next();
            System.out.println("键:"+ key+" 值:"+ map.get(key));
        }



        //map集合的遍历方式二: 使用values方法进行 遍历。    缺点: values方法只能返回所有 的值,没有键。
        Collection<String>  c = map.values(); //values() 把所有的值存储到一个Collection集合中返回。
        Iterator<String> it = c.iterator();
        while(it.hasNext()){
            System.out.println("值:"+ it.next());
        }
        */

        //map集合的遍历方式三: entrySet方法遍历。
        Set<Map.Entry<String,String>>  entrys = map.entrySet(); 
        Iterator<Map.Entry<String,String>> it = entrys.iterator();
        while(it.hasNext()){
            Map.Entry<String,String> entry = it.next();
            System.out.println("键:"+ entry.getKey()+" 值:"+ entry.getValue());
        }   
    }
}
  • HashMap 底层也是基于哈希表实现的

    • HashMap的存储原理:往HashMap添加元素的时候,首先会调用键的hashCode方法得到元素
      的哈希码值,然后经过运算就可以算出该元素在哈希表中的存储位置。

      • 情况1:
        如果算出的位置目前没有任何元素存储,那么该元素可以直接添加到哈希表中。

      • 情况2:如果算出
        的位置目前已经存在其他的元素,那么还会调用该元素的equals方法与这个位置上的元素进行比较,如果equals方法返回
        的是false,那么该元素允许被存储,如果equals方法返回的是true,那么该元素被视为重复元素,不允存储。

  • TreeMap : 也是基于红黑树(二叉树)数据结构实现的,
    特点:会对元素的键进行排序存储

    • TreeMap 要注意的事项:
      1. 往TreeMap添加元素的时候,如果元素的键具备自然顺序,那么就会按照键的自然顺序特性进行排序存储
      2. 往TreeMap添加元素的时候,如果元素的键不具备自然顺序特性,
        那么键所属的类必须要实现Comparable接口,把键的比较规则定义在CompareTo方法上
      3. 往TreeMap添加元素的时候,如果元素的键不具备自然顺序特性,而且键所属的类也没有实现Comparable接口,那么就必须在创建TreeMap对象的时候传入比较器

class Emp {//implements Comparable<Emp>{

    String name;

    int salary;

    public Emp(String name, int salary) {
        super();
        this.name = name;
        this.salary = salary;
    }


    @Override
    public String toString() {
        return "[姓名:"+this.name+" 薪水:"+ this.salary+"]";
    }

/*
    @Override
    public int compareTo(Emp o) {
        return this.salary - o.salary;
    }*/

}


//自定义一个比较器
class MyComparator implements Comparator<Emp>{

    @Override
    public int compare(Emp o1, Emp o2) {
        return o1.salary - o2.salary;
    }   
}

public class Demo {

    public static void main(String[] args) {
    /*  TreeMap<Character, Integer> tree = new TreeMap<Character, Integer>();
        tree.put('c',10);
        tree.put('b',2);
        tree.put('a',5);
        tree.put('h',12);
        System.out.println(tree);*/

        //创建一个自定义比较器
        MyComparator comparator = new MyComparator();

        TreeMap<Emp, String> tree = new TreeMap<Emp, String>(comparator);
        tree.put(new Emp("冰冰", 2000),"001");
        tree.put(new Emp("家宝", 1000),"002");
        tree.put(new Emp("习总", 3000),"003");
        tree.put(new Emp("克强", 5000),"005");

        tree.put(new Emp("财厚", 5000),"008");
        System.out.println(tree);
    }

}