黑马程序员-集合


黑马程序员-集合

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

概念:

        java中的集合也就是容器,容器就是用来存储对象用的,因此根据存储的特性上可以分为单列集合(Collection)和双列集合(Map)。

并且每一种容器都有自己的内部数据结构,所以我们会根据需要选择相应的容器。

 

集合框架结构:

单列集合:

 

      1.List:元素可以重复,且有顺序有角标(索引),怎么添加进去,就怎么取出来。(list的contains方法其实就是调用元素的equals方法去判断的)

               1-1 Vector:内部是数组数据结构,并且是同步的。(底层数组以100%增长)

               1-2 ArrayList:内部是数组数据结构,不是同步的,替代了vector。与LinkedList对比查询元素速度快,因为数组内存空间是连续的。(底层数组以50%增长)

               1-3 LinkedList:内部是链表数据结构,不是同步的,增删元素速度快,查询慢因为链表结构内存空间是不连续的。

      2.Set:元素不能重复,没有顺序。

               2-1 HashSet:内部是哈希表结构,不同步。(在添加元素时,先调用hashcode方法,如果hashcode方法返回值相同继续判断equals方法判断内容是否相同以保证元素的唯一)

               2-2 内部是二叉树结构,不同步。它有两种存放元素方式:
                      (1).按照元素的自然顺序。(实现Comparable节后,覆盖compareTo方法)
                      (2).给TreeSet集合指定比较器。(实现Comparator接口,实现compare方法)
                   注:这两种方式都是按照比较后的返回值进行确定位置的,正数就大,负数小,零表示这两个元素相同。
                   附:二叉树的节点分别存了三个要素,左边、 右边、父元素。在读取时是先读取左边元素在读取右边,最后读取父元素。
                          二叉树的 存放也是按照两元素比较后的值来确定的,为负时放左边,正时放右边,为零时不存。
                          其次二叉树在存放元素时都会将先前添加的元素进行折半,然后在确定下一个将添加的元素的位置这样来提高效率的。

  

LinkedList和ArrayList比较:

  

//ListIterator 是list特有的列表迭代器,该迭代器可以向后和向前遍历,还可以在迭代的同时对集合中的元素进行增删改查。
public class CollectionDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		  List<String> collection= new ArrayList<String>();
		  collection.add("abc1");
		  collection.add("abc2");
		  collection.add("abc3");
		  
		  //Iterator<String> it=collection.iterator();
		  ListIterator<String> it=collection.listIterator();
		  while(it.hasNext()){
			  Object element=it.next();
			  if(element.equals("abc2")){
				 // collection.add("abc4");//在迭代器迭代过程中,用集合的方法对元素进行了操作,此时迭代器并不知道刚刚加入的元素,所以抛出java.util.ConcurrentModificationException。
				                           //解决的办法是用列表迭代器同一对集合的元素进行迭代、操作。
				  it.add("abc4");
			  }else {
				System.out.println("next:"+element);
			}
		  }
		  System.out.println(collection);
		  SpeedTest();//选择容器时平凡增删数据用LinkedList,查找用ArrayList
	}
	//测试linkedlist和arraylist增删的速度
	public static void SpeedTest(){
		List<String> arraylList=new ArrayList<String>();
		List<String> linkedList=new LinkedList<String>();
		for(int i=0;i<1000000;i++){
			linkedList.add("abc"+i);
			arraylList.add("abc"+i);
		}
		long startTime=System.currentTimeMillis();
		for(int i=0;i<1000;i++){
		 linkedList.add(i, "aaa");
		}
		long endTime=System.currentTimeMillis();
		System.out.println("LinkedList增加元素用时:"+(endTime-startTime)+" ms");
		 startTime=System.currentTimeMillis();
		for(int i=0;i<1000;i++){
			arraylList.add(i, "aaa");
		}
		 endTime=System.currentTimeMillis();
		 System.out.println("ArrayList增加元素用时:"+(endTime-startTime)+" ms");
	}
}

运行结果:
next:abc1
next:abc3
[abc1, abc2, abc4, abc3]
LinkedList增加元素用时:0 ms
ArrayList增加元素用时:2531 ms   

因此证明在进行频繁增删操作时我们英应该选择LinkedList。

 

HashSet集合:

 

package cn.jiava.basic.collection;

import java.util.HashSet;
import java.util.Iterator;

//Set集合演示
public class SetDemo {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		HashSet set=new HashSet();
		set.add("aaa");
		set.add("bbb");
		set.add("ccc");
		set.add("ccc");
		set.add("ddd");
		//我们应该考虑最小内存开销,保证循环结束后迭代器被释放。
      for( Iterator it=set.iterator();it.hasNext();){
    	  System.out.println(it.next());
      }
	}
}


运行结果:
aaa
ddd
ccc
bbb

得出HashSet集合内部是哈希表,在存入对象时会先调用hashCode方法算哈希值,如果哈希值相同,则会调用对象的eqauls方法继续判断,如果返回true则认为对象重复,则不存入。同时存入的对象元素都是无序的。

LinkedHashSet:   

<span style="font-size:14px;"><strong>package cn.jiava.basic.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;

//Set集合演示
public class SetDemo {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		//LinkedHashSet 集合既可以保证元素的唯一,也可以保证元素的存入和取出是有序的。
		LinkedHashSet set=new LinkedHashSet();
		set.add("aaa");
		set.add("bbb");
		set.add("ccc");
		set.add("ccc");
		set.add("ddd");
		//我们应该考虑最小内存开销,保证循环结束后迭代器被释放。
      for( Iterator it=set.iterator();it.hasNext();){
    	  System.out.println(it.next());
      }
	}
}

运行结果:

aaa

bbb

ccc

ddd

 

TreeSet集合:

//如果TreeSet容器没有比较器,那么存入的对象具有自然顺序,否则报错。
public class Person implements Comparable{
	private int age;
	private String name;

	public Person() {
		super();
	}

	public Person(String name,int age ) {
		super();
		this.age = age;
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
  //在TreeSet容器没有比较器时,会调用此方法进行比较再存入容器。
 //在这里按照人的年龄进行比较
	@Override
	public int compareTo(Object o) {
		if(!(o instanceof Person)){
			throw new ClassCastException("类型不合法");
		}
		Person p=(Person) o;
		int temp=this.age-p.age;
		return temp==0?this.name.compareTo(p.name):temp;
	}

}
/TreeSet集合存入元素时根据元素自然顺序存入
public class TreeSetDemo {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
        TreeSet ts=new TreeSet();
        ts.add(new Person("zhangsan",22));
        ts.add(new Person("lishi",21));
        ts.add(new Person("wangwu",23));
        ts.add(new Person("wbngwu",23));//如果年龄相同,则按次要条件年龄进行比较存入
        ts.add(new Person("zhaoliu",20));
        Iterator it=ts.iterator();
        while(it.hasNext()){
        	Person person=(Person) it.next();
        	System.out.println(person.getName()+":::"+person.getAge());
        }
	}
}
<p>
	<span style="font-size:14px;">运行结果:</span>
</p>
<p>
	<span style="font-size:14px;">zhaoliu:::20

	lishi:::21

	zhangsan:::22

	wangwu:::23

	wbngwu:::23</span>
</p>
<p>
	<span style="font-size:14px;"></span>

	
</p>
<pre class="java" name="code">//TreeSet还可以指定比较器,如果有比较器的时候会覆盖存入对象的自然顺序。
public class ComparatorByName implements Comparator {

	@Override
	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 int compare(Object o1, Object o2) {
        return 1;
    }*/     
}
public class TreeSetDemo {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
        TreeSet ts=new TreeSet(new ComparatorByName());//指定容器的比较器
        ts.add(new Person("zhangsan",22));
        ts.add(new Person("lishi",21));
        ts.add(new Person("wangwu",24));
        ts.add(new Person("wangwu",23));//如果年龄相同,则按次要条件年龄进行比较存入
        ts.add(new Person("zhaoliu",20));
        Iterator it=ts.iterator();
        while(it.hasNext()){
        	Person person=(Person) it.next();
        	System.out.println(person.getName()+":::"+person.getAge());
        }
	}
}

运行结果:

lishi:::21
wangwu:::23
wangwu:::24
zhangsan:::22
zhaoliu:::20

从结果看出,当TreeSet传入自己的比较器后,尽管存入的对象有自己的自然顺序,但会被容器的比较器覆盖。

 

双列集合:

     1.HashTable: 内部是哈希表结构,是同步的,不允许null作为键和值。

     2.HashMap: 内部是哈希表结构,不同步的,允许null作为键和值。(HashSet内部就是通过HashMap实现的)

     3.TreeMap:内部是二叉树结构的,不同步的,可以对集合中建进行排序。(TreeSet内部通过TreeMap实现)

HashSet集合:

//HashMap键重复被覆盖
public class HashMapDemo {
	public static void main(String[] args) {
		HashMap<Person, String> hm=new HashMap<Person, String>();
		hm.put(new Person("zhangsan",22), "北京");
		hm.put(new Person("lishi",20), "深圳");
		hm.put(new Person("wangwu",21), "上海");
		hm.put(new Person("zhaoliu",25), "天津");
		hm.put(new Person("wangwu",21), "重庆");//会判断键的哈希值和equals方法是否相同,相同则覆盖。
		//Map.Entry为内部类,通过该内部类的getKey和getValue方法可获得键和值。
		for(Map.Entry<Person, String> me:hm.entrySet()){
			System.out.println(me.getKey().getName()+":::"+me.getKey().getAge()+"..."+me.getValue());
		}
	}
}

TreeMap集合:

//TreeMap和TreeSet存入元素一样,根据自然顺序和集合的比较器进行存入。
public class TreeMapDemo {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		TreeMap<Person, String> hm=new TreeMap<Person, String>(new ComparatorByName());//传入集合比较器
		hm.put(new Person("zhangsan",22), "北京");
		hm.put(new Person("lishi",20), "深圳");
		hm.put(new Person("wangwu",21), "上海");
		hm.put(new Person("zhaoliu",25), "天津");
		hm.put(new Person("wangwu",21), "重庆");
		//Map.Entry为内部类,通过该内部类的getKey和getValue方法可获得键和值。
		for(Map.Entry<Person, String> me:hm.entrySet()){
			System.out.println(me.getKey().getName()+":::"+me.getKey().getAge()+"..."+me.getValue());
		} 

	}

}


运行结果:

lishi:::20...深圳
wangwu:::21...重庆
zhangsan:::22...北京
zhaoliu:::25...天津

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------



 

 


 


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值