有了这篇博客再也不怕面试官问java的集合框架了!

集合框架

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

集合的特点

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

集合的数据结构

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

集合框架的顶层的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方法。
  • 5、其他:
    • boolean retainAll(Collection coll):取交集,如 c1.retainsAll(c2);c1中保留和c2中相同的元素,删除不同的元素
    • Object[] toArray():将集合转成数组

集合Collection下的子接口

  • List 有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复
  • Set 元素不允许重复,无序。

List特有的常见方法

都可以操作角标

  • 添加
    • void add(index,element)
    • void add(index,Collection);
  • 删除
    • Object remove(index);
  • 修改
    • Object set(index,element);
  • 获取
    • Object get(index);
    • int indexOf(Object);
    • int lastIndexOf(Object);
    • List subList(from , to );获取list的子集合,包含from位置的元素,不含to位置的元素
    • 注意:
/*以下代码通过Iterator遍历List集合,在迭代过程中,向list集合增加元素,会报出java.util.ConcurrentModificationException异常。即在Iterator迭代过程中不允许修改集合
*/
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next(); //java.util.ConcurrentModificationException  
	if(obj.equals("abc2")){
		list.add("abc9");
	}
	else
		System.out.println("next:"+obj);
	}
	
//此时可以通过ListIterator进行迭代,迭代过程中通过ListIterator对象操作集合
ListIterator it = list.listIterator();
		//它可以实现在迭代过程中完成对元素的增删改查。注意:只有list集合具备该迭代功能
		while(it.hasNext()){
			Object obj = it.next();
			if(obj.equals("abc2")){
			    it.add("abc9");
			}else
				System.out.println("next:"+obj);
		}

List接口的具体实现

  • Vector:内部是数组数据结构,是同步的。
  • ArrayList:内部是数组数据结构,是不同步的。代替Vector,查询速度快。
    • ArrayList容器中判断对象是否相同依据对象的equals方法。
    • 如调用ArrayList的 boolean contains(Object obj)\ boolean remove(Object obj)等方法时,依据obj中的equals方法如何实现判断对象是否相同
  • LinkedList:内部是链表数据结构,非同步的。增删元素的速度很快。
  • jdk1.6版本之前,如果LinkedList为空,调用getFirst()\getLast()\removeFirst\removeLast()方法会报异常(NoSuchElementException),jdk1.6新增peekFirst()\peekLast()\pollFirst\pollLast(),如果此时LinkedList为空,则直接返回null,不会抛异常。

set集合详解

set元素不可以重复,是无序的,Set接口中的方法和Collection是一致的。

  • HashSet:
    • 内部数据结构是哈希表,是不同步的
    • 哈希表确定元素是否相同
      • 1、判断的是两个元素的哈希值是否相同,如果相同,再判断两个对象的内容是否相同。
      • 2、判断哈希值是否相同,其实判断的是对象的hashCode方法。判断内容是否相同,用的是equals方法。
      • 注意:如果哈希值不同,是不需要判断equals的。
      • 使用元素的hashCode方法来确定位置,如果位置相同,再通过元素的equals来确定是否相同
//案例:将Person对象存入HashSet中,当姓名和年龄相同时,认为是同一对象。重写hashCode方法与equals方法
public class Person {

	private String name;
	private Integer age;
	public Person() {
	}
	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	public int hashCode() {
		System.out.println(this+"......hasCode");
		return this.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;
		System.out.println(this+"....equals....."+p);
		return this.name.equals(p.name) && this.age == p.age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
  • LinkedHashSet:有确定的迭代顺序的Set接口的实现
  • TreeSet:可以对set集合中的元素进行排序,是不同步的
    • 判断元素唯一性的方式:就是根据比较方法(compareTo)的返回结果是否是0,是0,就是相同的元素,不存。
    • TreeSet对元素进行排序的方式:
      • 让元素自身具备比较功能,元素需要实现Compareble接口,覆盖compareTo方法,如:
//Person类继承Comparable接口,实现compareTo方法
public class Person implements Comparable{

    ......
    
    public int compareTo(Object obj) {
		if( !(obj instanceof Person)){
			return 0;
		}
		Person p = (Person)obj;
		int temp = this.age - p.age;
		return temp == 0 ? this.name.compareTo(p.name) : temp;
	}
}
      • 让集合自身具备比较功能,定义一个自定义的比较类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。如:
   //自定义实现Comparator接口的比较类
public class ComparatorByName implements Comparator {
 public int compare(Object obj1, Object obj2) {
	if(!(obj1 instanceof Person)||!(obj2 instanceof Person )){
		return 0;
	}
	Person p1 = (Person)obj1;
	Person p2 = (Person)obj2;
	int temp = p1.getName().compareTo(p2.getName());
	return temp == 0 ? p1.getAge() - p2.getAge() : temp;
	}
}
  //创建TreeSet实例时,传入自定义的比较器
  TreeSet set = new TreeSet(new ComparatorByName());
  • 案例:TreeSet如何实现元素的按存入的顺序遍历
    • TreeSet底层为二叉树,要求存入的元素必须有序。每存入一个元素都与根节点的元素比较,若大于根节点,则放根节点的右子树;若小于则放根节点的左子树;若相等,则不存入。通过迭代器遍历时,为二叉树的中序遍历,即值最小的先遍历出。
    • 若按照对象存入的先后顺序遍历,则排序规则为后存入TreeSet集合中元素总是大于先存入的元素。则此时比较器应为:
  //自定义实现Comparator接口的比较类
public class ComparatorByName implements Comparator {
 public int compare(Object obj1, Object obj2) {
	return 1;
}
  //创建TreeSet实例时,传入自定义的比较器
  TreeSet set = new TreeSet(new ComparatorByName());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值