java集合Collection

 

集合总结:
 在集合中有两个接口是非常重要的,即Collection和Map;在这两个集合的基础上,又有一些完成特定功能
的其它子集合和实现类,下面就详细介绍一下其中非常重要的。
 下面代码是在API1.6版本下完成的,以下学习中的方法介绍请参考API

Collection  :java.util包中
 |--Set
  元素是无序的,所谓无序即不经其它处理,存入顺序和取出顺序是不同(因为底层的不同);
  元素不重复。
 |--List
  元素有序
  元素可重复

Collection中的方法是共有的方法,其中应该熟练掌握的有:
 对这些方法不在给予单独的介绍,在以下例子中用到时会有详细注释
 增加:
  boolean add(E e);
  boolean addAll(Collection<? extends E> c);
 删除:
   boolean remove(Object o);
   boolean removeAll(Collection<?> c);
   void clear();
 判断:
   boolean isEmpty();
   boolean contains(Object o);
   boolean containsAll(Collection<?> c);
 其它常用: int size();Iterator<E> iterator();//迭代是遍历集合非常常用的
 还有就是转换成数组

Set
 |--HashSet
  底层数据结构是哈希表,实现不同步,可以存储null;
  遍历:
   迭代器:是遍历集合的很好的方式,每个集合类中都有iterator方法,这是为了遍历的需求;
   高级for循环:能用迭代器遍历的,都能用高级for循环进行遍历;
  不重复:其特性是依赖于其底层实现结构,哈希表;在添加元素时,会进行比较,如果不相同,下添加
   比较方式:1、首先比较其哈希值是否相同;2、若哈希值相同,再比较其存储对象的内容是否相同
   这种比较方式是默认调用的
  注意:HashSet方法中的用到查找的方法如contains(),remove()等,都依赖于以上两种比较方式,所以
   对于自定义类型,一般要重写hashCode()和equals()方法(底层基于哈希表的都是如此)。
  在HashSet的例子中会对以上重写方法进行详细介绍,以后不再重复

 |--TreeSet
  底层数据结构是二叉树,实现不同步
  遍历:和HashSet的遍历方式相同;
  元素默认按自然顺序排序:对于自定义类型一般
   1、重写Comparable接口中的compareTo()方法让元素本身具有比较性;
   2、或者在定义集合时,传入参数比较器,比较器要实现Comparator接口中的compare()方法
   当两种方式都存在时,以第二种方式为主。
   注意:当类中已经写过compareTo()方法,但其比较方式不是自己想要的,这时一般不是去重写改写
   该方法,而是定义一个比较器,这在开发中是很常见的
  无重复:在进行添加时会排序,调用比较方法,当内容相同时就不在添加

List
 该集合进行有关查找,匹配的操作时,用到的是equals(),方法,所以一般要重写该方法
 凡是用到索引操作的都是该集合特有的方法
 |--Vector
  底层数据结构是可变长度数组,jdk1.0 线程同步,相对ArrayList,效率低,功能几乎相同,逐步被ArrayList取代
  长度初始10,100%增长
  枚举是Vector中特有方法,Enumeration elments()和Iterator方法相同,但有限考虑迭代器方法
  遍历:索引、迭代器、枚举、高级for循环
 |--ArrayList
  底层可变长度数组,jdk1.2 实现不同步,大致等同于Vector中的方法
  长度初始10,50%增长
  遍历:索引、迭代器、高级for循环
 |--LinkedList
  底层是链表,可以方便的模拟栈和队列
  遍历:索引,迭代器,高级for循环

 set集合特有方法:ListIterator<E> listIterator(int index),列表迭代器,其中提供了操作
  普通迭代器Iterator:在进行迭代操作时,不能进行集合操作,否则抛出异常ConcurrentModificationException
 所以迭代时,只能进行迭代方法的操作,不能进行添加,修改等。对于迭代器中的remove()方法,操作也有局限性,
 如:每调用一次next()方法,只能进行一次remove()操作,且必须和next()共同使用
  ListIterator:在该迭代器实现中提供了一些对集合操作的方法
   void add(E e);  //添加
   void remove();//删除
   void set(E e); //修改
   boolean hasPrevious(); //当前指向前一个是否有元素,逆向遍历
   int nextIndex();//当前指向下一个元素索引
   E previous();//
   int previousIndex();   
 这些方法使对集合的操作更加方便
 
 LinkedList中还提供了特别的方法:这也可以很方便的模拟栈和队列
  addFirst();
  addLast();

  //获取元素,不删除
  getFirst();//列表是 isEmpty 则抛出异常NoSuchElementException
  getLast();

  //获取元素,删除元素
  removeFirst();
  removeLast();

  jdk 1.6出现
   offerFirst();
   offerLast();

   peekFirst(); isEmpty  不抛异常,返回null
   peekLast();

   poolFirst(); //isEmpty  不抛异常,返回null
   poolLast();

 

//HashSet练习
import java.util.*;
public class Test
{
	public static void main(String[] args){
		simApp();
		//operatePerson();
	}

	/*
	简单的应用  其方法可以参见API,方法的应用其实很简单
	对于其方法应该熟练掌握的有
		下面牵涉到泛型,这个是jdk1.5之后新出的特性,是为了程序的健壮性,在定义集合时,声明什么样的类型
	就只能存储什么类型;当没有声明要存储什么类型时在编译时会有警告,能编译通过,但是在执行时可能会出错,
	所以一般都会加上泛型(关于泛型的详细介绍将在其他博客中详细介绍)
	*/
	public static void simApp(){
		无参构造,String类型  泛型类型String
		HashSet<String> hs = new HashSet<String>();  
		hs.add("zhangsan");  ///添加元素
		hs.add("lisi");
		hs.add("zhangsan");
		hs.add(null);  //HashSet中可以存储 null
		System.out.println(hs.size());
		/**
			迭代器是取出集合中元素的有效方式:在每个结合中都有 iterator()方法,在Iterator接口中有三个方法
		boolean hasNxet() 判断是否还有元素;
		E next()取出当前指针指向的元素,每执行一次,指针向后移动一位
		void remove()移除迭代器中当前指针指向的元素

		但迭代器操作有局限性,在介绍LinkedList时会说明不同
		*/
		/*for (Iterator<String> it = hs.iterator(); it.hasNext();)
		{
			String str = it.next();
			System.out.println(str);
		}*/
		
		///高级for循环进行遍历
		for (String s : hs)
		{
			System.out.println(s);
		}

		//输出结果为:null lisi  zhangsan 这也说明了Set集合的两个特性,无序,去重
		boolean flag = hs.remove("张三");//boolean remove(Object)  移除单个元素
	}

	//往hashSet中添加自定义对象时
	public static void operatePerson(){
		HashSet<Person> hs = new HashSet<Person>();
		hs.add(new Person("zhangsan", 30));
		hs.add(new Person("lisi", 25));
		hs.add(new Person("zhangsan", 40));

		for (Iterator<Person> it = hs.iterator(); it.hasNext();)
		{
			Person p = it.next();
			System.out.println(p);
		}
	}
}
/**
对于自定义类型,一般书写时要重写toString()方法,这也是为了便于输出操作
在下面这个Person类中,重写了hashCode()、equals() 和 toString()三个方法
*/
class Person
{
	private String name;
	private int age;

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

	//重写hashCode(),在此重写的目的就是让不同对象hashCode值尽量不同,这个值可以任意写,但是为了尽量让其
	//不同,用如下方式
	public int hashCode(){	
		return name.hashCode() + age*37;
	}
	
	//在此是重写Object类中的equals方法
	public boolean equals(Object obj){
		//instanceof 是关键字 ,用于判断传入的类型是否匹配
		if (!(obj instanceof Person))
		{
			throw new RuntimeException("类型不匹配");
		}
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}

	public String toString(){
		return ("name:" + name + "---age:" + age);
	}
}


 

 

//TreeSet练习

import java.util.*;

class Person implements Comparable<Person>
{
	private String name;
	private int age;

	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	//实现copareTo方法  姓名 年龄升序;在此我是通过调用compareTo方法,也可以不调用,自己写
	public int compareTo(Person p){
		int num = name.compareTo(p.name);
		//如果姓名相同,则比较年龄
		if (num == 0)
		{
			return new Integer(age).compareTo(new Integer(p.age));
		}
		return num;
	}

	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}

	public String toString(){
		return "name:" + name + "---age:" + age;
	}
}

//定义迭代器 姓名 年龄降序,  由于只有写了这一个方法,所以可以定义为内部类
class Cmp implements Comparator<Person>
{
	public int compare(Person p1, Person p2){
		int num = p2.getName().compareTo(p2.getName());
		if (num == 0)
		{
			return new Integer(p2.getAge()).compareTo(p1.getAge());
		}
		return num;
	}
}

public class Test
{
	public static void main(String[] args){
		//无参构造函数
		//TreeSet<Person> ts = new TreeSet<Person>();

		//带比较器的构造函数
		TreeSet<Person> ts = new TreeSet<Person>(new Cmp());

		ts.add(new Person("zhangsan", 30));
		ts.add(new Person("lisi", 23));
		ts.add(new Person("zhangsan", 30));
		ts.add(new Person("lisi", 18));
		
		for (Iterator<Person> it = ts.iterator(); it.hasNext();)
		{
			Person p = it.next();
			System.out.println(p);
		}

		/**
		没有调用比较器时 输出结果
		name:lisi---age:18
		name:lisi---age:23
		name:zhangsan---age:30
		*/

		/*
		带比较器的构造函数
		name:zhangsan---age:30
		name:lisi---age:23
		name:lisi---age:18
		*/
	}
}


 

//Vector练习

/**
枚举方法虽然不是常用,但是在一些地方还是会用到,在此只介绍枚举的用法
*/

import java.util.*;
public class Test
{
	public static void main(String[] args){
		Vector<String> v = new Vector<String>();
		
		//添加元素
		v.add("zhangsan");
		v.add("lisi");
		v.add("aisi");
		v.add("zhangsan");

		/*
		Enumeration接口中有两个方法
		boolean hasMoreElements();判断是否还有元素,相当于迭代器中的hasNext()
		E nextElements();取出下一元素,相当于next();
		*/
		Enumeration<String> e = v.elements();
		for (; e.hasMoreElements(); )
		{
			String str = e.nextElement();
			System.out.println(str);
		}

		/*
		在一些特殊地方需要用到枚举方法,需要用Vector进行存储,但是Vector效率不高,所以需要用其它的
		集合,但要自己实现Enumeration中的方法
		*/

		ArrayList<String> al = new ArrayList<String>();

		al.add("zhangsan");
		al.add("lisi");
		al.add("aisi");
		al.add("zhangsan");

		Enumeration<String> e1 = iToe(al.iterator());

		for (; e1.hasMoreElements(); )
		{
			String str = e1.nextElement();
			System.out.println(str);
		}
	}

	//将迭代器转成枚举  在内部类中访问本地变量,需要被声明为最终类型,所以加上final
	public static Enumeration<String> iToe(final Iterator<String> it){
		return new Enumeration<String>(){

			public boolean hasMoreElements(){
				return it.hasNext();
			}

			public String nextElement(){
				return it.next();
			}
		};
	}
}



 

//LinkedList练习

import java.util.*;
class Person
{
	private String name;
	private int age;

	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	//覆盖equals方法
	/*public boolean equals(Object obj){
		if (!(obj instanceof Person))
		{
			return false;
		}
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age; //equals此处的equals是字符串比较的
	}*/

	public String getName(){
		return name;
	}

	public int getAge(){
		return age;
	}

	public String toString(){
		return "name:" + name + "---age:" + age;
	}
}

public class Test
{
	public static void main(String[] args){
		//simApp();
		mulPerson();
	}

	//基本操作
	public static void simApp(){
		LinkedList<String> ll = new LinkedList<String>();

		ll.add("zhangsan");
		ll.add("lisi");
		ll.add("zhangsan");

		for (Iterator<String> it = ll.iterator(); it.hasNext(); )
		{
			//it.next();
			//it.remove();  //每调用一次next()方法,只能调用一次remove()方法
			//ll.add("fda");  //在迭代时,不能进行集合相关的操作,会发生异常
		}
	}

	//添加自定义类型
	public static void mulPerson(){

		ArrayList<Person> oa = new ArrayList<Person>();
		oa.add(new Person("zhangsan", 12)); 
		oa.add(new Person("lisi", 13));
		oa.add(new Person("wang", 12));
		oa.add(new Person("zhangsan", 12));
		
		Person pe = new Person("zhangsan", 12);

		//当Person类中没有重写equals()方法时,该操作不起作用,当写过后,该方法移除第一次查找到的元素,
		//对于后面有重复的,则不再操作
		boolean flag = oa.remove(pe);
		for (Iterator<Person> it = oa.iterator(); it.hasNext(); )
		{
			Person p = it.next();
			System.out.println(p.getName() + ":" + p.getAge());
		}
	}
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值