Java学习笔记(十五)--集合

一、集合和数组的区别

  • 长度: 数组长度固定,集合长度不固定
  • 内容: 数组必须存储同一种类型,集合可存储多种不同类型的数据
  • 数据类型: 数组可存储基本数据类型和引用数据类型,集合只能存储引用数据类型

二、集合

 因为需要存储变长数据,所以集合应运而生,Java集合主要由两个接口派生而出:Collection和Map.(本图来自网络)


Collection是Set,List,Queue的父类,因此Collection有的方法,子类则可直接拥有,Collection常用的方法如下:

方法名称 方法作用
boolean add(Object o) 向集合中添加一个 元素,添加成功返回true
boolean addAll(Collection c) 将集合c中的所有元素添加到集合中,成功则返回true
void clear() 清除集合中的所有元素
boolean contains(Object o) 返回集合中是否包含指定元素
boolean containsAll(Collection c) 集合中是否包含集合c中所有的元素
boolean isEmpty() 返回集合是否为空,空:true,否则返回false
Iterator iterator() 用于遍历集合中元素
boolean remove(Object o) 删除集合中指定元素
boolean removeAll(Collection c) 删除与集合c相同的元素,即求差集,删除一个元素及以上则返回true
boolean retainAll(Collection c) 从集合中删除与集合c不同的元素,即求交集
int size() 集合所包含元素个数
Object[] toArray() 集合转换为数组
1.Set集合

  • 特点:存储的元素不能重复
1.1HashSet类

  • 特点:能够快速查找被检索的对象,不能保证元素的排列顺序,不是线程安全的,集合元素可以为null
  • 原理:根据hashCode值计算存储位置,查找的时候也是根据hashCode值,所以效率很快,由于添加和查询都是根据数据本身进行的操作,所以数据不能重复,否则就无法准确定位是哪个数据。HashSet中每个存储元素的位置叫"桶",如果多个元素的hashCode值相同,但他们通过equals方法返回false,则可在同一个桶内放多个数据,这样就会引起性能下降。
     1.1.1 LinkedHashSet类

  •  原理:是HashSet的子集,依然使用hashCode值计算存储位置,同时使用链表维护元素次序使得元素看起来是以插入的顺序保存的,但它依旧不允许元素重复。    
1.2TreeSet类

  •   原理:是SortedSet接口的实现类,依旧不能添加重复的数据,通过Comparator对象比较两个集合元素,比较结果返回0表示两个元素相等
  • 常用方法及作用如下:

方法名称 方法作用
comparator() 若TreeSet采用定制排序,则返回使用的Comparator,若采用自然排序,则返回null
Object first() 返回集合中的第一个元素
Object last() 返回集合中的最后一个元素
Object lower(Object e) 返回集合中位于指定元素之前的元素
Object higher(Object e) 返回集合中位于指定元素之后的元素
SortedSet subSet(Object from,Object to) 返回此区间内的元素
SortedSet headSet(Object to) 返回子集,元素由第一个元素到to组成
SortedSet tailSet(Object o) 返回子集,由大于或等于o的元素组成

  • 自然排序:TreeSet调用Comparable(object obj)方法来比较两个元素之间的大小关系,按照升序排列,举例:
 public static void main(String[] args) {
        TreeSet nums = new TreeSet();
        nums.add(5);
        nums.add(2);
        nums.add(10);
        nums.add(-9);
        System.out.println(nums.add(-9));   //不能重复添加相同的数据
        System.out.println(nums);
        System.out.println(nums.first());
        System.out.println(nums.last());
        System.out.println(nums.headSet(4));
        System.out.println(nums.tailSet(5));
        System.out.println(nums.subSet(-3, 4));
    }

  • 定制排序: 使用Lambda表达式代替Comparator对象实现,举例:
public class TreeSetDemo2 {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet(((o1, o2) -> {
            M m1 = (M)o1;
            M m2 = (M)o2;
            return m1.age   >m2.age?-1:m1.age<m2.age?1:0;
        }));

        treeSet.add(new M(5));
        treeSet.add(new M(-3));
        treeSet.add(new M(9));
        System.out.println(treeSet);
    }
}

class M{
    int age;

    public M(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "M{" +
                "age=" + age +
                '}';
    }
}
1.3EnumSet类

  • 概述:专门为枚举定义的集合,其中的元素必须是指定枚举类型的枚举值
  • 常用的方法及作用:
方法名称 方法作用
EnumSet allOf(Class elementType) 创建一个包含指定枚举类里所有值的EnumSet集合
EnumSet complementOf(EnumSet s) 创建一个新的与指定枚举集合类型相同的枚举集合,两个集合并集是该枚举类的所有枚举值
EnumSet copyOf(Collection c) 使用一个普通集合创建枚举集合
EnumSet copyOf(EnumSet s) 创建一个与指定EnumSet具有相同元素,类型的EnumSet集合
EnumSet noneOf(Class elementType) 创建一个空集合,类型为指定枚举类型
EnumSet of(elemtnt1,element2,element3...) 创建包含多个枚举值的枚举集合
EnumSet range(E from , E to) 创建一个包含从from到to范围的所有枚举值的枚举集合

  • 举例
public class EnumSetDemo {
    public static void main(String[] args) {
//        创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
        EnumSet es1 = EnumSet.allOf(Season.class);
        System.out.println(es1);
//        创建一个EnumSet空集合,指定其集合元素是Season类的枚举值
        EnumSet es2 = EnumSet.noneOf(Season.class);
        System.out.println(es2);
//        手动添加两个元素
        es2.add(Season.WINTER);
        es2.add(Season.SPRING);
        System.out.println(es2);
//        以指定枚举值创建EnumSet集合
        EnumSet es3 = EnumSet.of(Season.SUMMER,Season.WINTER);
        System.out.println(es3);
        EnumSet es4 = EnumSet.of(Season.SUMMER,Season.WINTER);
        System.out.println(es4);
//        es5的元素类型与es4的元素类型相同,这两个元素之和为整个Season类的枚举值
        EnumSet es5 = EnumSet.complementOf(es4);
        System.out.println(es5);
    }
}

enum Season{
    SPRING,SUMMER,FALL,WINTER
}
Set类对比总结

  •  特点:凡是set集合,都不可以添加重复的数据
  • 对比分析:

    ①Set集合都是线程不安全的

    ②HashSet对比TreeSet:前者对基本的添加操作,查询操作比较快,因为不需要维护顺序,可直接根据hashCode计算位置,后者只有当需要保持排序的Set时,才应该使用TreeSet

    ③HashSet对比LinkedHashSet:前者对于普通的插入,删除操作效率较高,因为不需要去维护顺序开销,遍历时后者更快,因为后者是有顺序的

   ④EnumSet是所有Set集合中性能最好的,但是只能保存同一个枚举类的枚举值作为集合元素

2.List集合

 List集合代表一个元素有序 ,可重复的集合,集合中每个元素都有其对应的顺序索引,其典型的子类有两个,ArrayList和Vector类,Vector类是java1.0就有了,其方法名很长,ArrayList是线程不安全的,Vector是线程安全的,及时如此,也很少推荐使用Vector,ArrayList可通过多种其他方式实现线程安全。

List常用方法及作用如下:

方法名称 方法作用
void add(int index, Object element) 将element插入到集合的index处
boolean addAll(int index,Collection c) 将集合c所包含的所有元素都插入到index处
Object get(int index) 返回集合index索引处的元素
int indexOf(Object o) 返回对象o在集合中第一次出现的位置
int lastIndexOf(Object o) 返回对象o在集合中最后出现的位置
List subList(int fromindex,int toindex) 子集合
Object remove(int index) 删除并返回index索引处的元素
Object set(int index,Object element) 替换旧元素
void replaceAll(operator) 根据一定规则重新设置list集合中的所有元素
void sort(Comparator c) 根据一定规则对list集合元素排序
boolean hasPrevious() 返回该迭代器关联的集合是否还有上一个元素
Object previous() 返回该迭代器的上一个元素
void add(Object o) 在指定位置插入一个元素

3.Queue集合

 先进先出的特点,对比之前的集合类型,队列集合会有队列头和队列尾之说,所以会有取队列头元素和队列尾元素的方法,如add,element,offer,peek,poll,remove等具体不再赘述。

4.Map集合

  Map存储的是key-value对(具有映射关系的数据),key和value都可以是任何类型的数据,Map集合的key值是不允许重复的,该集合中的key和value之间是一一对应的,通过一个key只能找到一个唯一的value值。在Set中有HashSet,LinkedHashSet,SortedSet,TreeSet,EnumSet等子接口和实现类,Map的接口下有HashMap,LinkedHashMap,SortedMap,TreeMap,EnumMap等子接口和实现类,其常用的方法及作用如下:

方法名称 方法作用
void clear() 删除该Map对象中的所有key-value对
boolean containsKey() 是否包含指定的key
boolean containsValue(Object value) 是否包含一个或者多个value
Set entrySet() 返回Map中的key-value对所组成的Set集合
Object get(Object key) 根据指定key返回value,若不包含此key,则返回null
boolean isEmpty() 是否为空,为空则返回true
Set keySet() 返回Map中所有key组成的Set集合
Object put(Object key,Object value) 添加一个key-value对
void putAll)Map m) 将指定map中的key-value对复制到本map中
Object remove(Object key) 删除指定key对应的key-value对
int size() Map中所包含的key-value对个数
Collection values() 返回该Map所有value组成的Collection
Object getKey() 返回Entry里包含的key值
Object getValue() 返回Entry里包含的value值
Object setValue(V value) 设置该Entry里包含的value值
   

  • 像SortedMap就类似于SortedSet,SortedMap又派生出TreeMap子类,TreeMap是有顺序的,所以会有第一个,前一个,上一个,后一个的方法,同样类似于TreeSet有两种排序方式,自然排序和定制排序,TreeMap的所有key都必须实现Comparable接口。采用定制排序不要求key实现Comparable接口,需要传入一个Comparator对象。
  •  WeakHashMap实现类:与HashMap的区别是,前者的key只保留了对实际对象的弱引用,后者的key保留了对实际对象的强引用。意味着HashMap对象不被销毁,该HashMap对象的key所引用的对象就不会被垃圾回收。
public class WeakHashMapTest {
    public static void main(String[] args) {
        WeakHashMap whm = new WeakHashMap();
        whm.put(new String("语文"),new String("良好"));
        whm.put(new String("数学"),new String("及格"));
        whm.put(new String("英文"),new String("中等"));

        whm.put("java",new String("中等"));

        System.out.println(whm);
        System.gc();
        System.runFinalization();
        System.out.println(whm);
    }
}

运行结果:

{英文=中等, java=中等, 数学=及格, 语文=良好}
{java=中等}

前三个key-value对的key是匿名对象,WeakHashMap保留了他们的弱引用,所以就垃圾回收了,最后一个是一个字符串直接量,WeakHashMap会保留强引用,所以没有被垃圾回收。

  • IdentityHashMap实现类比较特殊,HashMap比较两个key相等的条件是通过equals方法比较返回true,且它们的hashCode值相等即可。而IdentityHashMap的两个key严格相等时才认为是同一个key(key1==key2)。
public class IdentityHashMapTest {
    public static void main(String[] args) {
        IdentityHashMap ihm = new IdentityHashMap();
        ihm.put(new String("语文"),89);
        ihm.put(new String("语文"),78);
        ihm.put("java",93);
        ihm.put("java",98);

        System.out.println(ihm);
    }
}

运行结果:

{语文=89, 语文=78, java=98}
  • EnumMap:创建时必须显示或隐式的指定对应的枚举类,不允许null为key,但允许null为value,,根据key的自然顺序维护key-value对的顺序。
  • Map的性能分析总结:EnumMap>HashMap>Hashtable(古老,线程安全)>TreeMap

5.操作集合工具类Collections

 该工具类提供了很多方法操作Set,List,Map集合。

  • 排序操作:reverse,shuffle,sort,swap,rotate
  • 查找、替换:binarySearch,max,min,fill,frequency,indexOfSubList,lastIndexOfSubList,replaceAll
  • 同步控制:synchronizedXXX()

猜你喜欢

转载自blog.csdn.net/zh15732621679/article/details/80002509