------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、集合框架
二、List
三、set
四、泛型
一、集合框架
1,集合框架
collection体系:共性内容不断向是向上抽取形成的结果
数组和集合都是容器,有什么共性与不同?
共性:都是容器,用来存储数据
区别:数组类型固定,长度固定
集合,可存储多个对象,长度可变,是专门用于存储对象的,范围更广
集合中,为什么定义了那麽多类?
:每个集合类都是一个特有的容器,区别在于存储数据的方式不同,即数据结构不同
框架图:
2, Collection定义了集合框架的共性功能。
(1),添加
add(e);
addAll(collection);
(2),删除
remove(e);
removeAll(collection);
clear();
(3),判断。
contains(e);
isEmpty();
(4),获取
iterator();
size();
(5),获取交集。
retainAll();
(6),集合变数组。
toArray();
3,迭代器
原理:定义了一个接口标准,由各个集合容器的内部类实现,接口引用变量可直接调用内部类的方法,完成迭代。
for(Iterater it=xxx.iterator();it.hasNext();)
it.next();
原理图:
4、代码演示
class CollectionDemo
{
public static void main(String[] args)
{
method_get();
}
public static void method_get()
{
ArrayList al = new ArrayList();
//1,添加元素。
al.add("java01");//add(Object obj);
al.add("java02");
al.add("java03");
al.add("java04");
/*
Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素。
while(it.hasNext())
{
sop(it.next());
}
*/
for(Iterator it = al.iterator(); it.hasNext() ; )
{
sop(it.next());
}
}
public static void method_2()
{
ArrayList al1 = new ArrayList();
al1.add("java01");
al1.add("java02");
al1.add("java03");
al1.add("java04");
ArrayList al2 = new ArrayList();
al2.add("java03");
al2.add("java04");
al2.add("java05");
al2.add("java06");
//al1.retainAll(al2);//去交集,al1中只会保留和al2中相同的元素。
al1.removeAll(al2);
sop("al1:"+al1);
sop("al2:"+al2);
}
public static void base_method()
{
//创建一个集合容器。使用Collection接口的子类。ArrayList
ArrayList al = new ArrayList();
//1,添加元素。
al.add("java01");//add(Object obj);
al.add("java02");
al.add("java03");
al.add("java04");
//打印原集合。
sop("原集合:"+al);
//3,删除元素。
//al.remove("java02");
//al.clear();//清空集合。
//4,判断元素。
sop("java03是否存在:"+al.contains("java03"));
sop("集合是否为空?"+al.isEmpty());
//2,获取个数。集合长度。
sop("size:"+al.size());
//打印改变后的集合。
sop(al);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
二、List
1,特点
list:有序的,元素可重复,因为有索引值(索引方式不同)。
ListIterator:是list特有的迭代器,可以在迭代过程中进行属性操作,因为它有索引值。
2,子类
(1),ArrayList,底层使用的数据结构,是数组结构:查询修改速度很快,添加删除速度较慢。线程不同步。
(2),LinkedList,底层使用的数据结构,是链表数据结构:增删快,查询慢。
(3),vector,底层是数组结构,线程同步。被ArrayList取代。(在操作上,vector可用枚举)
3,可变长度
ArrayList和vector默认长度为10,当用完后,会创建新数组并将原数据迁移。ArrayList创建的新数组长度为5,vectorw为10浪费空间。
4,linkedList
自己独有的first/last方法(1.6的替代方法):
(1),添加offerFirst/offerLast
(2),获取peekFirst/peekLast
(3),pollFirst/pollLast
使用这些方法,如果集合没有元素返回空
两种小数据结构:
堆栈:先进后出
队列:先进先出
5,ArrayList,LinkedList
包含,删除都调用了底层的equals方法,所有使用到该集合时,复写对应类中的equals方法很重要。
6、代码演示
import java.util.*;
class ListDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void method()
{
ArrayList al = new ArrayList();
//添加元素
al.add("java01");
al.add("java02");
al.add("java03");
sop("原集合是:"+al);
//在指定位置添加元素。
al.add(1,"java09");
//删除指定位置的元素。
//al.remove(2);
//修改元素。
//al.set(2,"java007");
//通过角标获取元素。
sop("get(1):"+al.get(1));
sop(al);
//获取所有元素。
for(int x=0; x<al.size(); x++)
{
System.out.println("al("+x+")="+al.get(x));
}
Iterator it = al.iterator();
while(it.hasNext())
{
sop("next:"+it.next());
}
//通过indexOf获取对象的位置。
sop("index="+al.indexOf("java02"));
List sub = al.subList(1,3);
sop("sub="+sub);
}
public static void main(String[] args)
{
//演示列表迭代器。
ArrayList al = new ArrayList();
//添加元素
al.add("java01");
al.add("java02");
al.add("java03");
sop(al);
ListIterator li = al.listIterator();
//sop("hasPrevious():"+li.hasPrevious());
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java02"))
//li.add("java009");
li.set("java006");
}
while(li.hasPrevious())
{
sop("pre::"+li.previous());
}
//sop("hasNext():"+li.hasNext());
//sop("hasPrevious():"+li.hasPrevious());
sop(al);
/*
//在迭代过程中,准备添加或者删除元素。
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(obj.equals("java02"))
//al.add("java008");
it.remove();//将java02的引用从集合中删除了。
sop("obj="+obj);
}
sop(al);
*/
}
}
三、set
1、元素是无序的(存取顺序不一致),元素不可重复。
2、hashSet
底层数据结构是哈希表。
hashSet是怎样保证数据的唯一性呢?
:是通过两个方法hashCode和equals方法来完成的。
如果元素hash值相同,判断equals值;
如果元素hash值不同,不判断equals值。
Note:
对于判断元素是否存在、以及删除等操作,依赖的事元素的hashCode和equals方法。
hashSet:底层使用的数据结构是,哈希表
3,哈希表数据结构特点:
先比较哈希值,哈希值若一样再比较是否是同一对象。如果都为true,存放在同一位置;否则存放不同位置。
4,treeSet
实现了Comparable接口,可以对set按自然顺序排序。
排序时要注意:当主要条件相同时,判断次要条件。
treeSet底层的数据结构是二叉树。
使用treeSSet的类需要实现comparable接口覆盖compareTo方法,可实现对元素的自然顺序排序,判断元素唯一性的compareTo方法的返回值return=0.
treeSet排序两种方式:
(1),让元素具有比较性(实现Comparable接口)
(2),让treeSet容器具有比较性(内置比较器)
5、代码演示
class HashSetTest
{
/*
往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。
需要复写元素类的hashCode和equals方法
*/
public static void sop(Object obj)
{
System.out.println(obj);
}
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("a2",12));
hs.add(new Person("a4",14));
//sop("a1:"+hs.contains(new Person("a2",12)));
hs.remove(new Person("a4",13));
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//复写hashCode方法
public int hashCode()
{
System.out.println(this.name+"....hashCode");
return name.hashCode()+age*37;
}
//复写equals方法
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println(this.name+"...equals.."+p.name);
return this.name.equals(p.name) && this.age == p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class TreeSetDemo
{
/*
需求:
往TreeSet集合中存储自定义对象学生。
想按照学生的年龄进行排序。
思路:
要么元素具有比较性,要么容器具有比较性
*/
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi08",19));
//ts.add(new Student("lisi007",20));
//ts.add(new Student("lisi01",40));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu = (Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
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)
{
//return 0;
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj;
System.out.println(this.name+"....compareto....."+s.name);
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;
}
}
四、泛型
1,由来
解决集合存取的安全机制
2,好处
(1).将运行时的异常转化到编译时,安全
(2).不用强制转化
3,泛型类
什么时候定义泛型类?当需要传入的类型不确定时。
4,泛型方法
给函数定义泛型:public <T> void get(T t)
5,静态方法的泛型
:不能使用类的泛型,只能定义静态泛型方法。
这是因为:静态加载时先于对象的,使用不到类上的泛型。
泛型方法和泛型类可以交替使用,互不影响。
6,泛型接口
7,泛型高级运用
(1),<?>占位符,不确定的类型,可以传指定类型;
(2),那么,我不想存一个,也不想存任意的,怎么办?
(3),泛型限定
---上限:<?Extends Person>,可以传Person及Person子类。
---下限:<? Super Person>
泛型限定,是泛型扩展用的。
8、代码演示
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);
}
}