我是靠谱客的博主 大气烤鸡,最近开发中收集的这篇文章主要介绍【黑马程序员】Java集合类,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 -------android培训、java培训、期待与您交流! ----------

1. Java集合        

        Java集合类也成Java容器类,是Java中实用的工具,实现了一些常用的数据结构和方法,方便开发者调用。集合类和数组不一样,数组中可以存放基本类型的变量也可以存放对象,容器类中只能存放对象(实际上是对象的引用)。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类,如下图是Collection接口的继承树:


        如图所示:Set和List接口是Collection的两个子接口,它们分别代表了无序集合和有序集合;Queue是Java提供的队列实现,有点类似于List。

        下图显示的是Map接口的子接口及其及继承树:


        所有的Map实现类用于保存具有映射关系的数据,上图显示了Map的众多实现类,它们的功能各有不同,但都是存放的键值对。

2.Set集合

    Set集合类似于一个罐子,放进去的元素是无序的。Set集合类似于Collection但Set集合不能存放相同的元素。

    Set判断两个元素是否相同不是通过 == 而是 equals() 方法。

1) HashSet类

    Hash是Set的典型实现类,也是Set中使用最多的类。HashSet使用Hash算法存放元素,有很好的存取和查找性能。

    特点:

    ①不能保证元素的排列顺序。

    ②不同步。当两个线程同时访问一个HashSet时,假设他们同时修改HashSet元素,必须通过代码保证同步性。

    ③集合元素可以是null。

    判断元素相同标准:

    HashSet通过equals()以及hashCode()两个方法判断两个元素是否相同。如果两个元素euqals()比较返回true但hashCode不同,HashCode同样认为这是两个不同的元素。

     示例:

class TestA {
    public boolean equals(Object obj){
        return true;
    }
}
    //类B的hashCode()方法总是返回1,但没有重写其equals()方法
class TestB {
    public int hashCode(){
        return 1;
    }
}
    //类C的hashCode()方法总是返回2,且有重写其equals()方法
class TestC {
    public int hashCode(){
        return 2;
    }
    public boolean equals(Object obj) {
        return true;
    }
}
public class HashSetTest {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        //分别向hs集合中添加两个TestA对象,两个TestB对象,两个TestC对象
        hs.add(new TestA());
        <span style="font-family: Arial, Helvetica, sans-serif;">hs</span><span style="font-family: Arial, Helvetica, sans-serif;">.add(new TestA());      //返回true,添加成功。两个对象的equals()虽然为true,但hashCode不同,HashSet视为不同对象</span>
        <span style="font-family: Arial, Helvetica, sans-serif;">hs</span>.add(new TestB());
        hs.add(new TestB());  <span style="font-family: Arial, Helvetica, sans-serif;">//返回true,添加成功。对象的hashCode恒定返回2,所以相等,但两个对象指向不同。使用Object类的equals()方法进行比较时返回false, ,HashSet视为不同对象</span>
        hs.add(new TestC());
        hs.add(new TestC()); //添加失败,两个对象的equals()返回true,且hashCode返回2相等,所以无法添加元素,返回false
        System.out.println(hs);
    }
}

    HashSet中euqlas()返回ture并且hashCode()相等才判断为同一元素,如果euqals()为true但hashCode()不同,则存放元素时按hash值存放。如果hashCode相等,但equals为false,则会在原来hashcode位置使用链式存放,会导致性能下降。

2) LinkedHashSet

    使用链表维护容器内元素的顺序,输出时与添加元素的顺序一致。其他特性与HashSet一致。

    示例:

public class LinkedHashSetTest {
    public static void main(String[] args) {
        LinkedHashSet lhs = new LinkedHashSet();
        lhs.add("天空飘来5个字");
        lhs.add("那都不是事");
        System.out.println(lhs);
        //删除 天空飘来5个字
        lhs.remove("天空飘来5个字");
        //重新添加 天空飘来5个字
        lhs.add("天空飘来5个字");
        System.out.println(lhs);
    }
}

3)TreeSet

         TreeSet是SortedSet接口的实现类。TreeSet中的元素总是有序的。

        TreeSet采用红黑树存放元素。当一个元素被添加到TreeSet中时,系统会调用对象的compareTo(Object obj)方法与容器的其他元素比较确定元素的存放位置。所以添加到TreeSet的元素必须实现Comparable接口,否则在添加时会抛出ClassCastException异常。如以下代码所示:

class Tmp {
}
public class TreeSetExceptionTest {
	public static void main(String[] args) {
		TreeSet ts = new TreeSet();
		//向TreeSet集合中添加两个Tmp对象
		ts.add(new Tmp());  //可以正常添加,因为容器没有元素,不用进行比较
		//由于Tmp类未实现Comparable接口所以,当向TreeSet中插入第2个元素时,系统会抛出异常
		ts.add(new Tmp());  
	}
}

    对于TreeSet而言,判断两个元素是否相等唯一的条件是compareTo()方法返回0;

    总结:HashSet和TreeSet是Set的两个典型实现。一般情况下HashSet的性能好于TreeSet,因为TreeSet需要维护红黑树来保持集合元素的次序。HashSet的子类LinkedHashSet的性能没有HashSet高,同样是要维护一个链表。但应为有链表所以LinkedHashSet的遍历速度优于HashSet,EnumSet的性能最好。

3. List集合
    List集合代表一个有序的,可重复的集合,集合的中每个元素都有对应的索引,可通过该索引随机访问集合中的元素。对应的数据结构为线性表。

    1) List接口
    List接口是Collection接口的子接口,扩展了一些线性表特有的方法:
    示例:

public class ListTest {
    public static void main(String[] args) {
        List names = new ArrayList();
        //向names集合中添加三个元素
        names.add(new String(""));
        names.add(new String("张三"));
        names.add(new String("李四"));
        System.out.println(names);
        //将新字符串对象插入在第二个位置
        names.add(1 , new String("王五"));
        for (int i = 0 ; i < names.size() ; i++ ) {
            System.out.println(names.get(i));
        }
        //删除第三个元素
        names.remove(2);
        System.out.println(names);
        //判断指定元素在List集合中位置:输出1,表明位于第二位
        System.out.println(names.indexOf(new String("王五"))); 
        //将第二个元素替换成新的字符串对象
        names.set(1, new String("王五"));
        System.out.println(names);
        //将names集合的第二个元素(包括)
        //到第三个元素(不包括)截取成子集合
        System.out.println(names.subList(1 , 2));
    }
}

    List判断元素相等是通过equals()方法。List接口中的indexOf()、remove()等需要差早和比较元素的方法都是通过equals()方法确定元素是否相等,而不是通过判断元素的引用对象是否是同一对象。
    示例:

class A {
    public boolean equals(Object obj) {
        return true;
    }
}
public class ListTest2 {
    public static void main(String[] args) {
        List names = new ArrayList();
        names.add(new String("张三"));
        names.add(new String("李四"));
        names.add(new String("王五"));
        System.out.println(names);
        //删除集合中A对象,将导致第一个元素被删除
        names.remove(new A());     
        System.out.println(names);
        //删除集合中A对象,再次删除集合中第一个元素
        names.remove(new A());     
        System.out.println(names);
    }
}

        2) ArrayList和Vertor实现类
       ArrayList和Vertor是List的两个典型实现类。两者内部使用数组存放元素,所以其内部有一个Object[]的动态数组。
       ArrayList和Vertor使用initialCapacity设置数组的长度,当元素数量超出数组的长度是,数组容量会自动增加。用户在使用两个集合类是无需关心initialCapacity的大小,系统会自动以及增长。当需要一次性添加大量元素时,可以将initialCapacity属性设置为一个较大的数字已减少系统扩充数组容量的次数,提升性能。
    示例:

 public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>(20);  //设置初始化容量为20,如不设置默认容量为10
    list.ensureCapacity(500);  //使用ensureCapacity()方法重行设置数组容量
    list.trimToSize(); //将ArrayList长度缩减到当前数组当前元素的数量,可以使ArrayList占用的空间最小化
 }

Vertor与ArrayList不同的是前者是线程安全的,当性能较ArrayList低,一般情况下不推荐使用。

4. Queue集合
        Queue用于模拟队列这种数据结构,队列是指FIFO的容器。队列的头部保存在队列中存放时间最长的元素,队列的尾部保存在队列中存放时间最短的元素。新元素插入在队列的尾部,访问元素操作会返回队列头部的元素。
        Queue定义了如下几个方法:
  • vod add(Object e)将指定元素插入队尾
  • Object elenent() 获取队列头部的元素,但不删除该元素
  • boolean offer(Object e)将指定元素加入此队列的尾部,性能较好
  • Object peek()获取队列头部的元素,但不删除该元素。
  • Object poll()获取队列头部的元素,并删除该元素。
        1)PriorityQueue实现类
        这是一个标准额队列实现类,PriorityQueue保存队列元素的顺序并不是按照加入的顺序,而是按队列元素的大小进行排序。当调用peek()和poll()方法是,是去除队列中最小的元素。下面是该类的用法:
public class PriorityQueueTest {
    public static void main(String[] args) {
        PriorityQueue pq = new PriorityQueue();
        //下面代码依次向pq中加入四个元素
        pq.offer(6);
        pq.offer(-3);
        pq.offer(9);
        pq.offer(0);
        //输出pq队列,并不是按元素的加入顺序排列,
        //而是按元素的大小顺序排列,输出[-3, 0, 9, 6]
        System.out.println(pq);
        //访问队列第一个元素,其实就是队列中最小的元素:-3
        System.out.println(pq.poll());
    }
}
        注意:PriorityQueue不允许插入null对象

        2)Deque和ArrayDeque实现类
        Deque是Queue的子接口,它代表一个双端队列,Deque不仅可以当作队列使用还可以当作栈使用。Deque提供了一个典型的实现类:ArrayDeque,从该名称来看,这是一个基于数组实现的双端队列。下面示例将ArrayDeque当作堆栈来使用:
public class ArrayDequeTest {
    public static void main(String[] args)  {
        ArrayDeque stack = new ArrayDeque();
        //依次将三个元素push入"栈"
        stack.push("大学英语");
        stack.push("高等数学");
        stack.push("大学物理");
        //输出:[大学英语, 高等数学 , 大学物理]
        System.out.println(stack);
        //访问第一个元素,但并不将其pop出"栈",输出:大学物理
        System.out.println(stack.peek());
        //依然输出:[大学英语, 高等数学 , 大学物理]
        System.out.println(stack);
        //pop出第一个元素,输出:大学物理
        System.out.println(stack.pop());
        //输出:[大学英语, 高等数学]
        System.out.println(stack);
    }
}
5. HashMap和Hashtable集合
        它们都是Map接口的实现类,它们之间的区别如下:
Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能高一点;但如果有多了线程访问同一个Map对象时,使用Hashtable实现类更好。
Hashtable不允许使用Null作为key和value,但HashMap可以使用null作为key或者value。
        下面演示null作为HashMap的key和value的情况:
public class NullInHashMap {
    public static void main(String[] args) {
        HashMap hm = new HashMap();
        //试图将两个key为null的key-value对放入HashMap中
        hm.put(null , null);
        hm.put(null , null);    //①
        //将一个value为null的key-value对放入HashMap中
        hm.put("a" , null);    //②
        //输出Map对象
        System.out.println(hm);
    }
}
        HashMap判断两个key相等的标准是:两个key通过equals()比较返回true,两个key的hashCode值相等。
        HashMap判断两个value相等的标准是:两个value通过equals()表叫返回true。下面程序演示了hashtable判断两个key相等和两个value相等的标准。
class A {
    int count;
    public A(int count) {
        this.count = count;
    }
    //根据count的值来判断两个对象是否相等。
    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        if (obj!=null &&
            obj.getClass()==A.class) {
            A a = (A)obj;
            return this.count == a.count;
        }
        return false;
    }
    //根据count来计算hashCode值。
    public int hashCode() {
        return this.count;
    }
}
class B {
    //重写equals()方法,B对象与任何对象通过equals()方法比较都相等
    public boolean equals(Object obj) {
        return true;
    }
}
public class HashtableTest {
    public static void main(String[] args)  {
        Hashtable ht = new Hashtable();
        ht.put(new A(60000) , "大学英语");
        ht.put(new A(87563) , "高等数学");
        ht.put(new A(1232) , new B());
        System.out.println(ht);
        //只要两个对象通过equals比较返回true,
        //Hashtable就认为它们是相等的value。
        //由于Hashtable中有一个B对象,
        //它与任何对象通过equals比较都相等,所以下面输出true。
        System.out.println(ht.containsValue("测试字符串"));  //①
        //只要两个A对象的count相等,它们通过equals比较返回true,且hashCode相等
        //Hashtable即认为它们是相同的key,所以下面输出true。
        System.out.println(ht.containsKey(new A(87563)));   //②
        //下面语句可以删除最后一个key-value对
        ht.remove(new A(1232));    //③
        //通过返回Hashtable的所有key组成的Set集合,
        //从而遍历Hashtable每个key-value对
        for (Object key : ht.keySet()) {
            System.out.print(key + "---->");
            System.out.print(ht.get(key) + "n");
        }
    }
}


最后

以上就是大气烤鸡为你收集整理的【黑马程序员】Java集合类的全部内容,希望文章能够帮你解决【黑马程序员】Java集合类所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部