您的位置:首页 > 编程语言 > Java开发

java学习之集合框架

2015-05-23 23:26 309 查看
集合类的由来:

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

    

集合的特点:

      1、用于存储对象的容器。

      2、集合的长度是可变的。

      3、集合中不可以存储基本数据类型值。

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

集合框架图:

                                       


框架的顶层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();  取出元素的方式:迭代器的对象必须依赖于具体容器,因为每一个容器的数据结构不同,

        所以该迭代器对象是在容器中进行内部实现的。

           对于使用容器者而言,具体的实现不重要,只要通过容器过去到该实现的迭代器的对象即可,也就是iterator方法。

    Iterator接口就是对所有的Collection容器进行元素取出的公共接口。

5、其他

         boolean retainAll(Collection coll);  取交集

         Object[] toArray();  将集合转成数组。

    

Collection
   ---List:有序(存入和取出的顺序一致),元素都有索引,元素可以重复。
   ---Set:元素不能重复,无序。

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

1、添加

         boolean add(E e);

         void add(int index, E element);

2、删除

         Object remove(int index);

3、修改:

         Object set(int index, E element)

4、获取:

         Object get(int index);

         int indexOf(object);

         int lastIndexOf(object);

         List subList(int fromIndex, int toIndex);

public static void showMethod1(List list)
{
//添加元素
list.add("asd1");
list.add("asd2");
list.add("asd3");
System.out.println(list);//[asd1, asd2, asd3]
//插入元素
list.add(1, "asd4");
System.out.println(list);//[asd1, asd4, asd2, asd3]
//删除元素
System.out.println("remove = " + list.remove(0));//remove = asd1
System.out.println(list);//[asd4, asd2, asd3]
//修改元素
System.out.println("set = " + list.set(1, "asd5"));//set = asd2  返回被修改的那个
System.out.println(list);//[asd4, asd5, asd3]
//获取元素
System.out.println("get = " + list.get(0));//get = asd4
//获取子列表
System.out.println("subList = " + list.subList(1, 2));//subList = [asd5]
}
取出元素方法:

public static void showMethod2(List list)
{
list.add("asd1");
list.add("asd2");
list.add("asd3");
list.add("asd4");
Iterator it = list.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
//List特有的取出元素的方式之一
for(int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}
}


list集合是可以完成对元素的增删改查

List:

    ---Vector:内部是数组数据结构,是同步的(线程是安全的)。增删,查询都很慢。

    ---ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。

    ---LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。

    

LinkedList:

   addFirst();

   addLast();

   JDK1.6后

   offerFirst();

   offerLast();

   

   getFirst();//获取但不移除,如果链表为空,抛出NoSuchElementException

   getLast();

   JDK1.6后

   peekFirst();//获取但不移除,如果链表为空,返回null

   peekLast();

   

   removeFirst();获取并移除,如果链表为空,抛出NoSuchElementException

   removeLast();

   JKD1.6后:

   pollFirst();//获取并移除,如果链表为空,返回null

   pollLast();

LinkedList练习代码:

public static void main(String[] args)
{
LinkedList link = new LinkedList();
//往链表头添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
Iterator it = link.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
System.out.println(link);//[abc4, abc3, abc2, abc1]
System.out.println(link.getFirst());//abc4  取得链表头元素,但不删除
System.out.println(link.getLast());//abc1  取得链表尾元素,但不删除
System.out.println(link.removeFirst());//abc4  删除链表头元素,返回被删除的元素
System.out.println(link.removeFirst());//abc3
System.out.println(link);//[abc2, abc1]
//利用removeFirst取得链表中的每个元素,但是结束后链表变为空
while(!link.isEmpty())
{
System.out.println(link.removeFirst());
}
System.out.println(link);//[]
}

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

    Set接口中的方法和Collection一致

    |---HashSet:内部数据结构是哈希表,是不同步的。

                            如何保证该集合的元素唯一性呢?

                            是通过对象的hashCode和equals方法来完成对象唯一性的。

                            如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。

                            如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。

                            如果为true,视为相同元素,不存入。如果为false,那么视为不同元素,就进行存储。

    

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

                            判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,如果是0就是相同元素,不存储。

          TreeSet对元素进行排序的方式一:

                                让元素自身具备比较功能,元素需要实现Comparable接口,覆盖compareTo方法。

                            如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?

                            可以使用TreeSet集合的排序方式二:

                                让集合自身具备比较功能,定义一个类实现Comparator(比较器)接口,覆盖compare方法。

                                将该类对象作为参数传递给TreeSet集合的构造函数。  

Set集合输出顺序和存入的顺序不一致。第五行和第八行都把字符串"xixi"添加到集合中,但是Set集合不能

存放相同的元素,所以没有添加进去。

public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add("haha");
hs.add("xixi");
hs.add("hehe");
hs.add("heihei");
hs.add("xixi");
Iterator it = hs.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
/*输出
* haha
* heihei
* xixi
* hehe*/
}


哈希表确定元素是否相同:

1、判断的是两个元素的哈希值是否相同。

       如果相同,再判断两个对象的内容是否相同。

2、判断哈希值相同,其实判断的是对象的hashCode方法。判断内容相同,用的是equals方法。

注意:如果哈希值不同,是不需要判断equals的。
用哈希表存储自定义对象时,一般需要覆盖其父类Object中的hashCode方法和equals方法,构造自己的判断是否相同的方式。

如果哈希表要保证存入和输出有序,那可以使用HashSet的子类LinkedHashSet

Map:一次添加一对元素。Collection一次添加一个元素

    Map也称为双列集合,Collection集合称为单列集合。

           其实Map集合中存储的就是键值对,必须保证键的唯一性。

           

常用方法:

1、添加:

      value put(key, value);返回前一个和key关联的值,如果没有返回null

2、删除:

      void clear();清空Map集合

      value remove (key);根据指定的key删除这个键值对      

3、判断:

      boolean containsKey(key);

      boolean containsValue(value);

      boolean isEmpty(); 

4、获取:

      value get(key);通过键获取值,如果没有该键,返回null。可以通过返回null,来判断是否包含指定键。

      int size();获取键值对的个数。

public static void method1(Map<Integer, String> map)
{
//添加元素
System.out.println(map.put(8, "wangcai"));//null 没有原来值,返回null
System.out.println(map.put(8, "xiaoqiang"));//wangcai 替换了原来的值,返回原来的值
map.put(2, "zhangsan");
map.put(5, "wangwu");
System.out.println(map);//{2=zhangsan, 5=wangwu, 8=xiaoqiang}
//删除
System.out.println("remove:" + map.remove(2));//remove:zhangsan
//判断
System.out.println("comtainskey:" + map.containsKey(5));//comtainskey:true
//获取
System.out.println("get:" + map.get(8));//get:xiaoqiang
}

获取map中的元素方式一:

private static void method2(Map<Integer, String> map)
{
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
//取出map中的所有元素。
//原理:通过keySet方法获取map中所有的键所在的Set集合,再通过Set的迭代器
//获取到每一个键,再对每一个键获取其对于的值即可。
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext())
{
Integer key = it.next();
System.out.println(map.get(key));
/*zhangsan
xiaohong
wangwu
zhaoming*/
}
}

获取map中的元素方式二:

private static void method3(Map<Integer, String> map)
{
/*
* 通过Map转成Set就可以迭代,找到另一个方法entrySet
* 该方法得到键和值的映射关系作为对象存储到了Set集合中,
* 而这个映射关系的类型就是Map.Entry类型。
*/
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> it = 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);
}
/*
* 5 : zhangsan
* 7 : xiaohong
* 8 : wangwu
* 9 : zhaoming
*/
}

获取map中的元素方式三:

private static void method4(Map<Integer, String> map)
{
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
Collection<String> values = map.values();
Iterator<String> it = values.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
/*zhangsan
xiaohong
wangwu
zhaoming*/
}

集合的一些技巧:

需要唯一吗?

需要:Set

          需要指定顺序吗?

                      需要:TreeSet

                      不需要:HashSet

                      但是想要一个和存储一直的顺序(有序):LinkedHashSet

不需要:List

            需要频繁增删吗?

                       需要:LinkedList

                       不需要:ArrayList

        

如何记住每一个容器的结构和所属体系?看容器名字

List:

     |---ArrayList

     |---LinkedList

     

Set:

     |---HashSet

     |---TreeSet

     

后缀名就是该集合所属的体系,前缀名就是该集合的数据结构。

看到array就要想到数组,就要想到查询快,有下标

看到link就要想到链表,就要想到增删快,就要想到add get remove + frist last的方法

看到hash就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashCode方法和equals方法  

看到tree就要想到二叉树,就要想到排序,就要想到两个接口Comparable,Comparator接口  

而且通常这些常用的集合容器都是不同步的。    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  迭代器 集合框架