黑马程序员——【学习笔记】集合——集合框架及Collectiony方法


------- android培训 java培训 、期待与您交流!----------


集合框架就是集合容器因为内部的数据结构不同,而不断向上抽取的系统化产物。


1 集合框架的结构


1.1 Collection接口

Collection接口是框架的顶层接口。因为Collection接口的子类并非全部都有角标(只有List子接口有,Set子接口没有),所以只有增删查三大方法,没有改(如果要改只能删除再添加,但是不能保证序列一致,或者使用有角标的List接口),但有判断。

1.1.1 增——添加

boolean add(E e):一次添加一个元素。并返回一个

boolean addAll(Collection):将一个容器中的元素添加到当前容器中。

public class Day16 {
	public static void main(String[] args){
		Collection c = new ArrayList();
		System.out.println(c.add(2313));
		System.out.println(c);
		System.out.println(c.add(2313));
		System.out.println(c);
		System.out.println(c.add(null));
		System.out.println(c);
		System.out.println(c.add("abcd"));
		System.out.println(c);
		System.out.println(c.add("efgh"+'a'+true));
		System.out.println(c);
	}
}
true
[2313]
true
[2313, 2313]
true
[2313, 2313, null]
true
[2313, 2313, null, abcd]
true
[2313, 2313, null, abcd, efghatrue]

PS:Collection的子类ArrayList可以存放不同的数据类型(StringBuffer也可以),但不能存放基本数据类型(StringBuffer可以),上程序之所以能放2313 'a'等,是因为jdk1.5后有自动装箱拆箱及机制。在数据被腐乳ArrayList之前自动把他们封装成基本数据类型封装类了。


1.1.2 删——删除

boolean remove(Object obj);删除一个指定对象。如果没有此对象就返回false

boolean removeAll(Collection coll);删除参数容器和本容器中相同的元素。

void clear();直接将容器中的元素清空。


1.1.3 判断

boolean contains(Object obj);是否包含指定元素。

boolean containsAll(Collection coll);是否包含指定容器中的元素。容器中元素发生变化为true

boolean isEmpty();判断集合中是否有元素

public class Day16 {
	public static void main(String[] args){
		Collection c = new ArrayList();
		c.add(2313);
		c.add(2313);
		c.add(null);
		c.add("abcd");
		c.add("efgh"+'a'+true);
		int i = 5;
		c.add(i);
		c.remove("haha");
		System.out.println(c);
		System.out.println(c.contains("haha"));
		System.out.println(c.containsAll(c));
		System.out.println(c.isEmpty());
		System.out.println(c.size());
	}
}

[2313, 2313, null, abcd, efghatrue, 5]
false
true
false
6


1.1.4 查——获取

int size();获取该集合的长度。

Interator iterator();取出元素的手段:迭代器。

boolean retainAll(Collection coll);保留两集合的交集元素并输出判断(有或没有交集)

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

1.2 迭代器

Iterator iterator();Iterator跟Collection一样,是一个接口。

因为每一个容器的数据结构都不同,所以该迭代器对象是在容器中进行内部实现的,也就是iterator方法在每个容器中的实现方式是不同的。java为了方便我们使用,统一封装成iterator给用户调用。

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

使用方法:作为集合对象的方法调用。Collection xxx = new ArrayList(); Iterator i = xxx.iterator();得到的不是Iterator实例,而是Iterator的运用于ArrayList的子类,这里运用了多态。

public class Day16{
	public static void main(String[] args){
		Collection coll = new ArrayList();
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		coll.add("abc4");
//		System.out.println(coll.next);
		System.out.println(coll);
		//使用iterator调用迭代器,
<span style="white-space:pre">		</span>//用while循环
		Iterator i =  coll.iterator();
		while(i.hasNext()){
			System.out.println(i.next());//next是迭代器的方法
		}
		//用for循环
		for(Iterator i1 = coll.iterator();i1.hasNext();){
			System.out.println(i1.next());
		}
	}

PS: 注意用while方法的话在循环完毕后迭代器iterator仍会存在。如果用for循环则可以在循环完毕后释放iterator,更干净。

注意使用迭代器iterator过程中,最好不要对集合进行操作,因为迭代器是事先读取集合长度后操作的,是属于迭代器的动作,如果同时进行了增删这个集合操作,则迭代器不知道读不读,应该读到哪里,即引发了并发操作异常。

所以在迭代器里,只能用迭代器的方法操作数据。原本的iterator迭代器只提供了move操作,即从集合中去除该元素。

如果我们需要对迭代中做更多的增删改查操作,就可以运用List类特有的迭代器ListIterator。

它具有add() set() 等方法。同时还有向前迭代的功能hasPrevious,previous

注意迭代器在循环中迭代完一次之后,不会回复首位的,它的状态已经被记录,如果再用它去迭代一次,只能一致输出null。

public class Day16{
	public static void main(String[] args){
		List l = new ArrayList();
		l.add("abc1");
		l.add("abc2");
		l.add("abc3");
		System.out.println("list="+l);
		Iterator i  = l.iterator();
		while(i.hasNext()){
//			i.next() = "abc";
			Object o = i.next();
			System.out.println(o);
//			System.out.println(i.next());
		}
	}
}


2 List、set

Collection的两个重要接口(仍然是一个接口)

——List:有序(存入和取出的顺序一致),元素都有索引(或角标),允许重复元素

——Set:元素不能重复,无序。(注意这里的无序不是说它的数据随机存放,而是不按照添加顺序存放——因为他们有自己的排序方式。HashSet是按HashCode和内容,TreeSet是按比较器comparator或让类本身具备可比性comparable)

2.1 List

除了Collection的方法,其特有的常见方法,基本是操作角标的方法(因为List有角标):

2.1.1 添加

void add(int index,E element):将元素插入指定角标位置。

boolean addAll(int index,collection c):将参数容器中的元素插入指定位置角标。

2.1.2 删除

Object remove(index);删除指定角标的元素

2.1.3 修改(因为有List有角标,所以允许修改操作)

Object set(index,element);指定角标修改元素

2.1.4 获取

Object get(index);获取特定角标的元素;

int indexOf(object);根据元素获取元素第一次的角标。如果没有元素,返回-1.

int lastIndexOf(object);根据元素获取元素最后出现的角标。

List subList(int from, int to);获取列表中的一部分,包含fromIndex,不包含toIndex。

PS:正因为List接口有角标,它可以按照角标来操作,比如按角标获取元素。所以List接口的子类对象除了按照Collection的方法使用迭代器iterator之外,还可以像传统的数组一样获用角标获取。

public class Day16{
	public static void main(String[] args){
		List l = new ArrayList();
		for (int x=0;x<10;x++){
			l.add("haha_"+(x+10));
		}
		System.out.println(l);
		Iterator i = l.iterator();
		while(i.hasNext()){
			System.out.print(i.next());
		}
		System.out.println();
		System.out.println("\r\n"+"-------------");
		for(Iterator i1=l.iterator();i1.hasNext();){
			System.out.print(i1.next());
		}
		System.out.println();
		System.out.println("\r\n"+"-------------");
		for(int x=0;x<l.size();x++){//角标取值,List接口特有的方法,因为List有角标
			System.out.print(l.get(x));
		}
	}
}


3 List下面的主要类

List:

——Vector:内部是数组结构,是同步的。增删,查询都很慢

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

——LinkedList:内部是链表结构,是不同步的,增删的速度很快,查询速度慢。


3.1 LinkedList特有的主要方法

因为LinkedList是链表结构,只有索引,没有角标,所以它没有按照角标操作的方法。

增加

addFirst();将指定元素放入LinkList开头,

addLast();将指定元素放入LInkList结尾。

在jdk1.6后,他们分别被offerFirst(); offerLast();代替,没有区别。


获取

getFirst();按索引顺序获取,但不移除,如果链表为空,抛出NoSuchElementException

getLast();按倒叙的索引顺序获取,但不移除

jdk1.6后更新方法peekFirst();替代getFirst(),peekLast();替代getLast();获取但不移除,如果链表为空,返回null

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

removeLast();

jdk1.6后更新方法为pollFirst();替代removeFirst();获取并移除,如果链表为空,返回null。pollLast();同理。

package demo;

import java.util.*;

public class Day17 {
	public static void main(String[] args){
		LinkedList lk = new LinkedList();
		lk.add("haha1");
		lk.addFirst("haha2");
		lk.addLast("haha3");
		System.out.println(lk);
		Iterator i = lk.iterator();
		while(i.hasNext()){
			System.out.println(i.next());
		}
		System.out.println("-----------");
		for(Iterator i1 =lk.iterator();i1.hasNext();)
			System.out.println(i1.next());
		System.out.println("-----------");
		Iterator i2 = lk.iterator();
		String[] s=new String[lk.size()];
		int x = 0;
		while(i2.hasNext()){			
			s[x]=(String)i2.next();
			x++;
		}
		for(String str:s){
			System.out.println(str);
		}
		System.out.println("-----------");
		while(lk.peek()!=null){
//		while(true){	
			System.out.println(lk.poll());
		}
//		System.out.println(lk);
//		while(true){
//			System.out.println();
//		}
	}
}

注意第二次用lk的迭代器必须要再创建一个Iterator i2,否则会全部输出null


4 Set

4.1 Set是跟List区分开的一个接口,其元素不可以重复,而且无序。

——HashSet:内部哈希表结构,是不同步的。

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

public class Day17{
	public static void main(String[] args){
		Set s = new HashSet();
		s.add("haha1");
		s.add("haha2");
		s.add("haha3");
		s.add("haha4");
		Iterator i = s.iterator();
		while (i.hasNext())
			System.out.println(i.next());
	}
}
haha4
haha3
haha2
haha1

并非按照输入顺序输出,而是按照Hash地址输出。


4.2 HashSet用哈希表确定元素是否相同。

①先判断两个元素的哈希值是否相同。用HashCode()方法得到元素的哈希值。

②如果相同,再判断两个对象的内容是否相同(因为有可能两个元素被人为设定为同一个哈希值)。用的是equals方法。

如果HashCode不同,就不再判断内容equals

/*在HashSet集合中存储Person对象,如果姓名和年龄相同,视为同一人,是为相同元素
 * 
 */
class Person{
	private String name;
	private int age;
	Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public int hashCode(){
//		System.out.println(name.hashCode());
		return name.hashCode()+age*11;
	}
	public boolean equals(Object obj){
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误");
		Person p = (Person)obj;
		return this.name.equals(p.name)&&this.age==p.age;
	}
}
class Day17{
	public static void main(String[] args){
		HashSet hs = new HashSet();
		hs.add(new Person("zhangsan",10));
		hs.add(new Person("lisi",14));
		hs.add(new Person("wangwu",12));
		hs.add(new Person("zhangsan",10));
		System.out.println(hs);
		Iterator i = hs.iterator();
		while(i.hasNext()){
			Person obj = (Person)i.next();
			System.out.println(obj.getName()+"..."+obj.getAge());
		}		
	}
}
[demo.Person@aa9c30e2, demo.Person@d09b2ca5, demo.Person@32b12d]
zhangsan...10
wangwu...12
lisi...14


PS:HashSet判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals。


4.3 LinkedHashSet

LinkedHashSet可以使其无序变有序,但仍然不可重复。

public class Day17{
	public static void main(String[] args){
		LinkedHashSet lh = new LinkedHashSet();
		lh.add("zhangsan"); 
		lh.add("lisi");     
		lh.add("wangwu");   
		lh.add(10); 
		lh.add("wangwu");
		System.out.println(lh);
	}
}
[zhangsan, lisi, wangwu, 10]


4.4 TreeSet

TreeSet底层是二叉树结构。可以给set集合中的元素进行指定顺序排序,默认情况下是通过元素自然顺序排序的。

保证元素元素唯一性的依据是看compareTo方法返回结果是否为0,是0就视为相同,不存。(而HashSet是根据hashCode和equals的判断来保证为一)



如果不要按照对象中具备的自然顺序进行排序。或者对象不具备自然排序,就让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法,

然后把其对象传入集合作为集合使用的比较器。

blic class Day17{
	public static void main(String[] args){
		TreeSet<String> ts = new TreeSet(new LengthCom());
		ts.add("hahaaaa");
		ts.add("heheaa");
		ts.add("xixia");
		ts.add("wuwuaaaa");
		System.out.println(ts);
	}
}
class LengthCom implements Comparator{
	public int compare(Object o1,Object o2){
		String s1 = (String)o1;
		String s2 = (String)o2;
		return(s1.length()-s2.length());
	}
}
这是按照字符串长度来让TreeSet排序

PS:如果类本身实现了Comparable接口,覆盖了comparaTo(Object o)方法,即自身具备了比较性,而同时TreeSet的构造函数中也传入了比较器Comparator(覆盖了compare(Object o1,Object o2)方法),那么将以比较器的比较规则为准。


4.5 Vector

Vertor的一个特殊方法:

Enumeration elements();Enumeration是一个接口,它生产一系列元素,一次生成一个。该方法类似调用迭代器,为早期使用的方法。

Boolean hasMoreElements();判断是否有下一个元素。

nextElements();获取下一个元素。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值