集合

来源:互联网 发布:ci 数据库配置 编辑:程序博客网 时间:2024/06/07 08:35

集合

集合类

集合类的由来

对象用于封装特有数据,对象多了需要存储;如果对象的个数不确定,就使用集合容器进行存储。

集合特点

    1. 用于存储对象的容器。    2. 集合的长度是可变的。    3. 集合中不可以存储基本数据类型值。

集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。


数组和集合类区别

数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。

集合框架的构成及分类:

集合框架



Collection 接口

集合框架的顶层Collection接口


Collection 的常见方法

  1. 添加

    ​ boolean add(Object obj);
    ​ boolean addAll(Collection coll);

  2. 删除

    ​ boolean remove(Object obj);
    ​ boolean removeAll(Collection coll);
    ​ void clear();

  3. 判断

    ​ boolean contains(Object obj);
    ​ boolean containsAll(Collection coll);
    ​ boolean isEmpty();

  4. 获取

    ​ int size();
    ​ Iterator iterator(); 获取迭代器

  5. 其他

    ​ boolean retainAll(Collection coll);取交集
    ​ Object toArray();将集合转成数组

Collection
​ |–List:有序(存入和取出的顺序一致),元素都有索引(角标),允许重复元素。
​ |–Set:元素不能重复,无序。



List

​ List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
​ |–Vector:内部是数组数据结构,是同步的。增删,查询都很慢。
​ |–ArrayList:内部是数组数据结构,是不同步的,替代了Vector,查询的速度快。
​ |–LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。

List 特有的常见方法有一个共性特点就是都可以操作角标

  1. 添加

    ​ void add(index,element) 在指定的索引位插入元素。
    ​ void addAll(index,collection) 在指定的索引位插入一堆元素。

  2. 删除

    ​ Object remove(index) 删除指定索引位的元素。 返回被删的元素

  3. 修改

    ​ Object set(index,element) 对指定索引位进行元素的修改

  4. 获取:

    ​ Object get(index) 根据角标获取元素
    ​ int indexOf(object) 根据元素获取角标,从前往后查找
    ​ int lastIndexOf(object) 根据元素获取角标,从后往前查找
    ​ List subList(from,to) 截取一段集合

    List集合可以完成对元素的增删改查。

import java.util.ArrayList;import java.util.List;public class ListDemo{       public static void main(String[] args){            List list = new ArrayList();            show(list);      }       public static void show(List list){             //添加元素            list.add( "abc1" );            list.add( "abc2" );            list.add( "abc3" );            System.out.println(list);             //插入元素            list.add(1, "abc2" );             //删除元素            System.out.println( "remove:" + list.remove(2));             //修改元素            System.out.println( "set:" + list.set(1,"abc8" ));             //获取元素:            System.out.println( "get:" + list.get(0));                   //获取子列表            System.out.println( "sublist:" + list.subList(1,2));            System.out.println(list);      }}

在迭代器(Iterator)获取数据的过程中,不要使用集合操作元素,会出现异常,可以使用 Iterator 接口的子接口ListIterator 来实现在迭代过程中完成对元素的增删改查,只有 list 集合具备该迭代功能。



Set

Set 中元素不可以重复,是无序。

Set接口中的方法和Collection 一致。
​ |–HashSet:内部数据结构是哈希表,是不同步的。

​ |–LinkedHashSet:有序,hashset的子类。

​ |–TreeSet:可以对Set集合中的元素进行排序,是不同步的。


HashSet

HashSet 集合保证元素唯一性是通过元素的hashCode方法,和equals方法完成的。

当元素的hashCode值相同时,才继续判断元素的equals是否为true。 如果为true,那么视为相同元素,不存。如果为false,那么存储。 如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。


哈希表的原理:

  1. 对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。
  2. 哈希值就是这个元素的位置。
  3. 如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。
  4. 存储哈希值的结构,我们称为哈希表。
  5. 既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。 这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。


对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。

import java.util.HashSet;import java.util.Iterator;class Person{       public String name;       public int age;       public Person(){      }       public Person(String name,int age){             this.name = name;             this.age = age;      }       public int hashCode(){             return name.hashCode() + age * 39;      }       public boolean equals(Object obj){             if(this == obj)                   return true ;//同一个对象放两次,直接返回true             if(!(obj instanceof Person))                   throw new ClassCastException("类型错误");            Person p = (Person)obj;             return this .name.equals(p.name) && this.age == p.age;      }}public class HashSetTest{       public static void main(String[] args){            HashSet hs = new HashSet();            hs.add( new Person("lisi4" ,24));            hs.add( new Person("lisi7" ,27));            hs.add( new Person("lisi1" ,21));            hs.add( new Person("lisi9" ,29));            hs.add( new Person("lisi7" ,27));            Iterator it = hs.iterator();             while(it.hasNext()){                  Person p = (Person)it.next();                  System.out.println(p.getName() + "..." + p.getAge());            }      }}



TreeSet

TreeSet 用于对 Set 集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。

TreeSet 集合的底层是二叉树进行排序的。

TreeSet方法保证元素唯一性的方式是参考比较方法的结果是否为0,如果是 0,视为两个对象重复,不存储。

如果元素不具备比较性,在运行时会发生ClassCastException异常。


TreeSet 对元素进行排序有两种方式

1.让元素自身具备比较功能

元素就需要实现Comparable接口,覆盖compareTo方法。

import java.util.Iterator;import java.util.TreeSet;class Person implements Comparable{       public String name;       public int age;       public Person(){      }       public Person(String name,int age){             this.name = name;             this.age = age;      }       public int hashCode(){             return name.hashCode() + age * 39;      }       public boolean equals(Object obj){             if(this == obj)                   return true ;             if(!(obj instanceof Person))                   throw new ClassCastException("类型错误");            Person p = (Person)obj;             return this .name.equals(p.name) && this.age == p.age;      }       public int compareTo(Object o){            Person p = (Person)o;             //先按照年龄排序,再按照年龄排序,以免年龄相同的人,没有存进去。             int temp = this.age - p.age;             return temp == 0?this.name.compareTo(p.name):temp;      }}public class TreeSetDemo{       public static void main(String[] args){            TreeSet ts = new TreeSet();             //以Person对象年龄进行从小到大的排序            ts.add( new Person("zhangsan" ,28));            ts.add( new Person("wangwu" ,23));            ts.add( new Person("lisi" ,21));            ts.add( new Person("zhouqi" ,29));            ts.add( new Person("zhaoliu" ,25));            Iterator it = ts.iterator();             while(it.hasNext()){                  Person p = (Person)it.next();                  System.out.println(p.getName() + ":" + p.getAge());            }      }}

2.让集合自身具备比较功能

定义一个类实现Comparator接口,覆盖compare方法,将该类对象作为参数传递给TreeSet集合的构造函数。

import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;//创建了一个根据Person类的name进行排序的比较器。class ComparatorByName implements Comparator{       public int compare(Object o1,Object o2){            Person p1 = (Person)o1;            Person p2 = (Person)o2;             int temp = p1.getName().compareTo(p2.getName());             return temp == 0?p1.getAge()-p2.getAge() : temp;      }}public class TreeSetDemo{       public static void main(String[] args){            TreeSet ts = new TreeSet(new ComparatorByName());             //以Person对象年龄进行从小到大的排序            ts.add( new Person("zhangsan" ,28));            ts.add( new Person("wangwu" ,23));            ts.add( new Person("lisi" ,21));            ts.add( new Person("zhouqi" ,29));            ts.add( new Person("zhaoliu" ,25));            Iterator it = ts.iterator();             while(it.hasNext()){                  Person p = (Person)it.next();                  System.out.println(p.getName() + ":" + p.getAge());            }      }}

如果自定义类即实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器的比较规则为准。


Map 集合

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

Map常用方法

1、添加
​ value put(key,value):返回前一个和key关联的值,如果没有返回null。

2、删除
​ void clear():清空map集合。
​ value remove(Object key):根据指定的key删除这个键值对。

3、判断
​ boolean containsKey(key);
​ boolean containsValue(value);
​ boolean isEmpty();

4、获取
​ value get(key):通过键获取值,如果没有该键返回null。当然可以通过返回null,来判断是否包含指定键。
​ int size():获取键值对个数。


把map集合转成set的方法:
Set keySet();
Set entrySet();//取的是键和值的映射关系。

对应了两种map取值的方式。

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);      }       public static void method(Map<Integer,String> map){            map.put(8, "王五");            map.put(2, "赵六");            map.put(7, "小强");            map.put(6, "旺财");             //取出map中的所有元素,有两种方式。             //第一种方式,通过keySet方法获取map中所有的键所在的set集合             //在通过set的迭代器获取到每一个键。             //再对每一个键通过map集合的get方法获取其对应的值即可。            Set<Integer> keySet = map.keySet();            Iterator<Integer> it = keySet.iterator();             while(it.hasNext()){                  Integer key = it.next();                  String value = map.get(key);                  System.out.println(key + ":" + value);            }            //第二种方式             //Iterator<Map.Entry<Integer,String>> it = map.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常用的子类:
​ |–Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
​ |–Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
​ |–HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。替代了Hashtable.
​ |–TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。

import java.util.HashMap;import java.util.Iterator;class Student {       public String name;       public int age;       public Student(){      }       public Student(String name,int age){             this.name = name;             this.age = age;      }       public int hashCode() {             final int prime = 31;             int result = 1;            result = prime * result + age;            result = prime * result + ((name == null) ? 0 : name.hashCode());             return result;      }       public boolean equals(Object obj) {             if (this == obj)                   return true ;             if (obj == null)                   return false ;             if (getClass() != obj.getClass())                   return false ;            Student other = (Student) obj;             if (age != other.age)                   return false ;             if (name == null) {                   if (other.name != null)                         return false ;            } else if (!name.equals(other.name))                   return false ;             return true ;      }}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);            }      }}

LinkedHashSet,LinkedHashMap 这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。

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);            }      }}



使用集合的技巧:

  • 看到Array就是数组结构,有角标,查询速度很快。
  • 看到link就是链表结构:增删速度快,而且有特有方法。
  • 看到hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
  • 看到tree就是二叉树,就要想到排序,就想要用到比较。
  • 存储的是一个元素时,就用Collection
  • 存储对象之间存在着映射关系时,就使用Map集合。
  • 保证唯一,就用Set
  • 不保证唯一,就用List。



Collections

Collections 是一个工具类,内部提供的都是静态方法。它的出现给集合操作提供了更多的功能。

Collections.sort(list);//list集合进行元素的自然顺序排序。 Collections.sort(list,new ComparatorByLen());///按指定的比较器方法排序。Collections.max(list); //返回list中字典顺序最大的元素。 Collections.binarySearch(list,"zz");//二分查找,返回角标。Collections.reverseOrder();//逆向反转排序。 Collections.shuffle(list);//随机对list中的元素进行位置的置换。


Collection 和 Collections的区别

Collections 是个 Java.util 下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
Collection 是个 java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。

数组转集合:

//将arr数组转成list集合。//可以通过list集合中的方法来操作数组中的元素:isEmpty()、contains、indexOf、setArrays.asList(arr);

集合转数组:

Collections.toArray();
原创粉丝点击