java学习之集合框架

集合类的由来:
    对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储。
    
集合的特点:
      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接口  
而且通常这些常用的集合容器都是不同步的。    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值