黑马程序员 java学习笔记——集合框架1

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

概述

为什么出现集合类?

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

数组和集合同是容器,它们有何不同?

1、数组虽然也可以存储对象,但长度是固定的,集合长度是可变的。
2、数组可以存储基本数据类型,集合只能存储对象。

集合类的特点

1、集合只用于存储对象
2、集合长度是可变的
3、集合可以存储不同类型的对象。

为什么会出现这么多的容器?

因为每一个容器对数据的存储方式都有不同,这个存储方式称之为:数据结构。


Collection的共性方法

Collection的方法,请参看下图:

示例代码如下:
import java.util.*;
/*
1、add方法的参数类型是Object,以便接受任意类型对象。
2、集合中存储的都是对象的引用(地址)。
*/
public class CollectionDemo{
	public static void main(String[] args){
		//创建一个集合容器,使用Collection接口的子类,ArrayList
		ArrayList a1=new ArrayList();
		//1、添加元素。
		a1.add("aaa");
		a1.add("bbb");
		a1.add("ccc");
		a1.add("ddd");
		a1.add("eee");
		//打印集合
		sop(a1);
		//3、删除元素
		al.remove("aaa");
		//a1.clear();	//清空集合
		sop(a1);
		//4、判断元素
		sop("ccc是否存在"+a1.contains("ccc"));
		sop("集合是否为空"+a1.isEmpty());
		
		//2、获取个数,集合长度
		sop("size:"+al.size());
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

迭代器

迭代器,其实就是集合取出元素的方式。
把元素的取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素,如此一来取出方式就被定义成了内部类。
由于每一个容器的数据结构不同,所以取出的动作细节也不一样,但它们有共性的内容:判断和取出,所以可以将这些共性内容抽取。
这些内部类都符合一个规则,该规则就是Iterator。
如何获取集合的取出对象呢?
通过一个对外提供的方法,iterator()
示例代码如下:
import java.util.*;
public class CollectionDemo{
	public static void main(String[] args){
		
		ArrayList a1=new ArrayList();
		a1.add("aaa");
		a1.add("bbb");
		a1.add("ccc");
		a1.add("ddd");
		a1.add("eee");

		for(Iterator it=a1.iterator();it.hasNext();){
			sop(it.next());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

List接口的共性方法

请参看下图



示例代码如下:
import java.util.*;
public class CollectionDemo{
	public static void main(String[] args){
		
		ArrayList a1=new ArrayList();
		a1.add("aaa");
		a1.add("bbb");
		a1.add("ccc");
		a1.add("ddd");
		a1.add("eee");
		sop("原集合是:"+a1);
		//在指定位置上添加元素
		a1.add(1,"zzz");
		sop("新集合是:"+a1);

		//删除指定位置上的元素
		a1.remove(2);

		//修改元素
		a1.set(2,"abc");

		//通过角标获取元素
		sop("get(1):"+a1.get(1));

		sop("index="+a1.indexOf("abc"));
		List sub=a1.subList(1,3);
		sop("sub="+sub);
		
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

ListIterator接口

List集合特有的迭代器,ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator的方法是有限的,只能对元素进行判断、取出、删除的操作。如果想要其他的操作如添加、修改等,就需要用到其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。

示例代码如下:
import java.util.*;
public class CollectionDemo{
	public static void main(String[] args){
		ArrayList a1=new ArrayList();
		a1.add("aaa");
		a1.add("bbb");
		a1.add("ccc");

		sop(a1);
		ListIterator li=al.listIterator();
		while(li.hasNext()){
			Object obj=li.next();
			if(obj.equals("bbb"))
				li.add("zzz");
		}
		sop(a1);
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

枚举

查阅API,发现List中有一个名为Vector的子类,它里面没有迭代器,而是又一个enumeration的方法,这就是枚举。
枚举就是Vector特有的取出方式。
仔细查看后发现它和迭代器很像,其实枚举和迭代器是一样。只是因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。

示例代码如下:
import java.util.*;
public class CollectionDemo{
	public static void main(String[] args){
		Vector v=new Vector();
		v.add("aaa");
		v.add("bbb");
		v.add("ccc");

		Enumeration en=v.elements();
		while(en.hasMoreElements()){
			System.out.println(en.nextElement());
		}
	}
}

LinkedList中的特有方法

请看下图





示例代码如下:
import java.util.*;
public class CollectionDemo{
	public static void main(String[] args){
		LinkedList link=new LinkedList();

		link.addFirst("aaa");
		link.addFirst("bbb");
		link.addLast("ccc");
		link.addLast("ddd");

		sop(link);
		sop(link.getFirst());
		sop(link.getLast());
		sop(link.removeFirst());
		sop(link.removeLast());
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}


HashSet

Set是Collection的子接口,它的特点是存入的元素是无无序的,不可重复的。
在它之下,有两个常用接口,HashSet和TreeSet。
其中,HashSet的底层是哈希表数据结构,线程非同步;TreeSet的底层是二叉树数据结构,可以对set集合中的元素进行排序

Set接口的子类能保证元素的唯一性,HashSet是如何保证元素唯一性的呢?

是通过元素的两个方法,hashCode和equals来完成。hashCode方法返回元素的哈希值,如果哈希值不相同,则两个元素为不同的,不添加。
如果哈希值相同,那么会接着运行equals方法,查看两个元素是否相同。相同则不添加,不相同才添加。

示例代码如下:
class Person{
	private String name;
	private int age;
	Person(String name.int age){
		this.name=name;
		this.age=age;
	}
	public int hashCode(){
		return name.hashCode()+age*21;
	}
	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;
	}
	public String toString(){
		return name+"::"+age;
	}
}

public class Demo{
	public static void main(String[] args){
		HashSet hs=new HashSet();
		hs.add(new Person("a1",11));
		hs.add(new Person("a2",12));
		hs.add(new Person("a3",13));
		hs.add(new Person("a4",12));
		hs.add(new Person("a4",14));

		for(Iterator it=hs.iterator();it.hasNext();){
			Person p=(Person)it.next();
			sop(p);
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

TreeSet

TreeSet也是Set的子类,能够保证元素的唯一性。它的底层是二叉树,能够是实现默认排序。
示例代码如下:
public class Demo{
	public static void main(String[] args){
		TreeSet ts=new TreeSet();
		ts.add("cba");
		ts.add("abcd");
		ts.add("aaa");
		ts.add("bca");
		for(Iterator it=hs.iterator();it.hasNext();){
			sop(it.next());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

TreeSet集合实现元素唯一性的两种方式:

1、自然排序(元素具备比较性)
TreeSet的无参构造,要求对象所属的类实现Comparable接口,复写其中的compareTo方法。
2、比较器排序(集合具备比较性)
TreeSet的带参构造,要求构造方法接收一个实现了Comparator接口的对象。

代码示例:让对象自己具备比较性

import java.util.*;
class Student implements Comparable{
	private String name;
	private int age;
	Student(String name,int age){
		this.name=name;
		this.age=age;
	}
	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s=(Student)obj;
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
			return this.name.compareTo(s.name);
		return -1;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}

public class Demo{
	public static void main(String[] args){
		TreeSet ts=new TreeSet();
		ts.add(new Student("wangda",20));
		ts.add(new Student("wanger",19));
		ts.add(new Student("wangsan",25));
		ts.add(new Student("wangsi",19));

		for(Iterator it=ts.iterator();it.hasNext();){
			Student stu=(Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}

当对象的比较性不是我们想要的时,就可以自定义比较器,然后传给TreeSet。

示例代码如下:

import java.util.*;
class Student implements Comparable{
	private String name;
	private int age;
	Student(String name,int age){
		this.name=name;
		this.age=age;
	}
	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s=(Student)obj;
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
			return this.name.compareTo(s.name);
		return -1;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}

class MyCompare implements Comparator{
	public int compare(Object o1,Object o2){
		Student s1=(Student)o1;
		Student s2=(Student)o2;
		int num=s1.getName().compareTo(s2.getName());
		if(num==0){
			return s1.getAge()-s2.getAge();
		return num;
	}
}
public class Demo{
	public static void main(String[] args){
		TreeSet ts=new TreeSet(new MyCompare());
		ts.add(new Student("wangda",20));
		ts.add(new Student("wanger",19));
		ts.add(new Student("wangsan",25));
		ts.add(new Student("wangsi",19));

		for(Iterator it=ts.iterator();it.hasNext();){
			Student stu=(Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}

泛型

JDK1.5版本后出现的新特性。用于解决安全问题,是一个安全机制。

泛型的好处

1、运行期间的classCastException转移到编译时期,方便程序员解决问题,让 运行期问题减少,较安全。
2、避免强制转换麻烦。

书写泛型的格式

通过< >来定义要操作的引用数据类型。其实< >就是来接收数据类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
如:ArrayList<String> al=new ArrayList<String>()
PS:自JDK7.0后,第二个<>中的内容也可不写

示例代码如下:
import java.util.*;
public class Demo3{
	public static void main(String[] args){
		ArrayList<String>al=new ArrayList<>();//JDK7.0出现的新特色,第二个<>中不用传入类型。
		al.add("aaa");
		al.add("bbb");
		al.add("ccc");
		for(Iterator<String>it=al.iterator();it.hasNext();){
			sop(it.next());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

泛型类

什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候。早期定义Object 来完成扩展,现在定义泛型来完成扩展。
示例代码如下:
class Worker
{
}
class Student
{
}
class Utils<QQ>
{
	private QQ q;
	public void setObject(QQ q){
	this.q = q;
	}
	public QQ getObject(){
		return q;
	}
}
class Demo3{
	public static void main(String [] args){
	  Utils<Worker>  u= new Utils<Worker>();
	  u.setObject(new Worker());
	  Worker w = u.getObject();
	}
}

泛型方法

泛型类定义的泛型,在整个类中有效。泛型类的对象明确要操作的具体类型后,所有要操做的类型就已经固定了。
为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
示例代码如下:
class Demo{
	public <T> void show(T t){
		System.out.println("show:"+t);
	}
	public <Q> void print(Q q){
		System.out.println("print:"+t);
	}
}
class GenericDemo4{
	public static void main(String [] args){
		Demo d = new Demo();
		d.show(new Integer(4));
		d.print("hehe");
		d.show("hahah");
	}
}

静态泛型方法

静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上
示例代码如下:
class Demo<T>{
	public  void show(T t){
		System.out.println("show:"+t);
	}
    public <Q> void print(Q q){
    	System.out.println("print:"+q);
    }
    public  static <W> void method(W t){
    	System.out.println("method::"+t);
    }
}
public class GenericDemo5{
	public static void main(String [] args){
		Demo<String> d1 = new Demo<String>();
		d1.print(5); 
		d1.show("hahah");
		Demo.method("hehehehe");
	}
}

泛型限定

?:通配符,也可以理解为占位符。
?extends E:可以接受E类或者E的子类型 上限
?super E:可以接受E类型或者E的父类型 下限
示例代码如下:
import java.util.*;
class Person{
	private String name;
	Person(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}
}
class Student extends Person{
	private String name;
	Student(String name){
		super(name);
	}
}
class GenericTest{
	public static void main(String[] args){
		ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("abc1"));
		al.add(new Person("abc2"));
		al.add(new Person("abc3"));
		sop(al);
		ArrayList<Student> al1 = new ArrayList<Student>();
		al1.add(new Student("abc--1"));
		al1.add(new Student("abc--2"));
		al1.add(new Student("abc--3"));
		sop(al1);
	}
	public static void sop(ArrayList<? extends Person> al){
		Iterator<? extends Person> it = al.iterator();
		while(it.hasNext()){
			sop(it.next().getName());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
} 

----------------------  ASP.Net+Android+IO开发S .Net培训 、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值