Java库中的常用集合(Collection/List/Set/Map)

来源:互联网 发布:北京网络职业学院招聘 编辑:程序博客网 时间:2024/05/18 00:13

一、Collection<E> 接口

1.1、常用方法

 /*  *增删操作  */ boolean add(E e) boolean remove(Object o) /*  *集合操作  */ //对于Set接口就是求并集,对于List接口就是将两列表连接起来  boolean addAll(Collection<? extends E> c)  //对于Set接口就是求差集  boolean removeAll(Collection<?> c)        //对于Set接口就是求交集 boolean retainAll(Collection<?> c)       /*  *查找某一个或几个元素在集合中是否存在  */ boolean contains(Object o) boolean containsAll(Collection<?> c) 
  • 以上方法都会涉及集合元素的比较,这些比较都是通过调用显式参数的equals()方法来完成的,所以需要重写equals()方法。
  • 以上方法的隐式参数和显式参数都只要求实现了Collection接口即可,所以可以出现隐式参数和显式参数一者为Set,一者为List的情况(但这种情况,在实现正确的equals()方法的约束下,永远返回false)。

equals()方法重写示例:

/* *情形一:如果子类能够拥有自己的相等概念,则对称性需求将强制采用getClass进行检测 */class Employee{    public String name;    public int age;    public double[] bwh;    //...    @Override    public boolean equals(Object obj){ //equals()方法的入参必须为Object类型        if(this ==  obj) return true;        if(obj == null) return false;        if(getClass() != obj.getClass()) return false;        Employee other = (Employee)obj;        return Objects.equals(name,other.name) //引用类型比较            && age == other.age                //基本类型比较            && Arrays.equals(bwh,other.bwh);   //数组比较    }}/* *情形二:如果由超类决定相等的概念,那么就可以使用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较 */class Employee extends SuperClassName{    public String name;    public int age;    public double[] bwh;    //...    @Override    public boolean equals(Object obj){             if(this ==  obj) return true;        if(obj == null) return false;        if(!(obj instanceof SuperClassName)) return false;        SuperClassName other = (SuperClassName)obj;        //superName、superAge等是父类的属性        return Objects.equals(superName,other.superName)             && superAge == other.superAge                            && Arrays.equals(superbwh,other.superbwh);      }}

重写equals()方法的同时,也必须重写hashCode()方法:

class Employee{    public String name;    public int age;    public double height;    public double[] bwh;    //...    @Override    public int hashCode(){        int c = 7;    //最好为质数。防止键的集聚        return c * Objects.hashCode(name)        //引用类型的哈希值             + c * age                           //int型的哈希值             + c * new Double(height).hashCode() //double型的哈希值             + c * Arrays.hashCode(bwh);         //数组的哈希值    }}
  • 当equals()方法返回true时,两个对象的hashcode也必须相同;当equals()方法返回false时,两个对象的hashcode在大多数情况是不同的,在少数情况下相同。
  • 集合类判断两个对象是否相等,是先判断hashcode是否相等,再判断equals()返回值是否为ture,只有两者都相等时,才认为该两个对象是相等的。所以若两个相同的对象有不同的hashcode,就会将两个相同的对象插入到Set或Map中。
  • 所谓散列冲突,是指集合类在判断两个对象是不同的之后,将两者的hashcode经过运算,发现两者在桶(bucket)中的位置是相同的。两者的hashcode不相同时有可能出现散列冲突,两者的hashcode相同时一定会出现散列冲突。所以就算不同的对象有相同的hashcode,也不会影响集合类的正常运行。

1.2、迭代器方法 Iterator<E> iterator()

迭代器使用示例:

Collection<String> c = new ArrayList<String>();Iterator<String> iter = c.iterator();while(iter.hasNext()){    String element = iter.next();    if(...){        iter.remove();    }}

只有对自然有序的集合使用迭代器添加元素才有实际意义。
                ——摘自《Core Java》

  • 所以Collection接口的迭代器没有add()方法,而List接口的迭代器才有add()方法。
  • 在执行 Iterator iter = c.iterator() 时,相当于生成了该集合的一个迭代器实例,若使用该迭代器实例以外的方法修改集合(包括集合自身的方法和其它迭代器实例的方法),就会抛出Concurrent ModificationException异常。
  • 迭代器在add或remove时,会额外改变自己独有的游标,所以在遍历集合时进行增删操作不会出现误操作。
  • 迭代器每次执行next()方法时,都会重新复制当前集合,所以迭代器可以实时反应集合的变化。

二、List<E> 接口

2.1、常用方法

//增boolean add(E e)void add(int index, E e) //删boolean remove(Object o)E remove(int index) //改E set(int index, E element)//查 E get(int index) int indexOf(Object o) //获取子集合List<E> subList(int fromIndex, int toIndex) //获取迭代器ListIterator<E> listIterator()  ListIterator<E> listIterator(int index) 

2.2、迭代器方法 ListIterator<E> listIterator()

比Iterator多出来的方法:

//Iterator只有删和查的操作,ListIterator还增加了增和改的操作void add(E e) void set(E e)  

三、Set<E> 接口

3.1、常用方法

//增boolean add(E e) //删boolean remove(Object o) 

四、Map<K,V> 接口

List接口、Set接口是继承自Collection接口的,而Map接口与Collection接口是平行的关系。

4.1、常用方法

//增、改V put(K key, V value) void putAll(Map<? extends K,? extends V> m)//查V get(Object key)boolean containsKey(Object key) boolean containsValue(Object value) //删V remove(Object key) 

4.2、Map的视图

三种视图:

//键值对集Set<Map.Entry<K,V>> entrySet() //键集Set<K> keySet()//值集(不是集)Collection<V> values() 

视图使用示例:

Map<String,Employee> staff = new HashMap<String,Employee>();for(Map.Entry<String,Employee> entry : staff.entrySet()){    String key = entry.getKey();        //取键    Employee value = entry.getValue();  //取值    //...    entry.setValue(e); //重新设值}

注意点:

entrySet()和keySet()返回的Set,既不是HashSet也不是TreeSet,而是实现了Set接口的某个其它类的对象。同时Set接口扩展了Collection接口,因此可以与使用任何集合一样使用entrySet()和keySet()返回的Set。
                ——摘自《Core Java》

  • values()的返回类型是Collection而不是Set,是因为所谓“值集”并不是集,因为有可能重复。

五、类型转换

5.1 不同集合类之间的转换

//通过各自的构造函数ArrayList(Collection<? extends E> c) LinkedList(Collection<? extends E> c)HashSet(Collection<? extends E> c)

关键点在于这些构造函数的入参都仅仅要求是Collection,So elegant!

5.2 集合类与数组之间的转换

/* *数组转换为集合类 */String[] arr ={"a","b","c"};List<String> list = Arrays.asList(arr); //此处list不可修改 //或直接 List<String> list = Arrays.asList("a","b","c"); List<String> arrList = new ArrayList<String>(list);//此处arrList可修改/* *集合类转换为数组 */ List<String> arrList = new ArrayList<String>(); String[] arr = new String[arrList.size()]; arrList.toArray(arr);

六、Java库中的具体集合

Java库中的具体集合
                ——摘自《Core Java》

参考连接:
正确重写hashCode的办法
ArrayList源代码分析
Iterator的remove()和Collection的remove()
Arrays.asList()注意

0 0
原创粉丝点击