集合(Collection):
定义:用于存储对象的可变长度的容器。
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。
就使用集合容器进行存储。
集合特点:
1,用于存储对象的容器。
2,集合的长度是可变的。
3,集合中不可以存储基本数据类型值。
数组的特点:
1、只能存储单一类型的对象。2、数组的大小一旦规定不能再改变。
集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。集合中常用类的继承关系如下:
Collection:该接口中定义了集合的共性方法。如下:
1,添加。
booleanadd(Object obj):
booleanaddAll(Collection coll):
2,删除。
booleanremove(object obj):
booleanremoveAll(Collection coll);
voidclear();
3,判断:
booleancontains(object obj)
booleancontainsAll(Colllectioncoll);
boolean isEmpty():判断集合中是否有元素。
4,获取:
Int size():获取容器大小。
Iterator iterator():取出元素的方式:迭代器。
5,其他:
booleanretainAll(Collection coll);取交集。
Object[]toArray():将集合转成数组。
演示代码如下:
package collectionTest;
import java.util.*;
public class CollectionTest {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("01");
c.add("02");
c.add("03");
c.add("04");
System.out.println(c);
c.add("01");//能够添加重复元素
System.out.println(c);
Collection<String> c1 = new ArrayList<String>();
c1.add("09");
c1.add("08");
c.addAll(c1);//添加一个集合中的所有元素
System.out.println(c);
c.remove("01");//删除元素
System.out.println(c);
c.removeAll(c1);//删除另一个集合中的所有元素
System.out.println(c);
System.out.println(c.contains("02"));//判断是否包含某元素
System.out.println(c.isEmpty());//判断集合是否为空
System.out.println(c.size());//返回集合长度
}
}
迭代器:Iterator。
所有 Collection 集合共性的取出方式。
迭代器的由来:每一个容器都应该有取出功能。这些功能定义都是一样,因为每个容器的数据结构不一样,这些功能实现的具体方式也不同。这些实现方式应该在容器类的内部,在类的内部对对类中的数据进行操作更方便。取出功能的实现比较复杂,因而将它定义为一个容器的内部类,这些内部类。每个容器的定义取出功能的内部类都有相同的部分,将其抽取出来,就形成了Iterator接口。
而每一个容器都在其内部对该接口进行了内部类的实现。
也就是将取出方式的细节进行封装。通过iterator方法对外提供了一个取出元素的对象。
在使用时,通常通过两个方法来完成。
1,判断容器中是否有元素hasNext()方法。2,取出元素next()方法。需要取出所有元素时,可以通过循环,java建议使用for循环。因为可以对内存进行一下优化。
注意:在迭代时,next方法每调用一次,内部指针就会自定往下走。在循环,next方法调用一次即可,否则会出现想不到的结果。
注意:在迭代过程中,不能使用集合中的方法来操作集合中的元素。会发生并发修改异常(CurrentModificationException)。因此,Iterator具有很大的局限性。
例如:for(Iterator it =c.iterator();it.hasNext();;)
{
Objectobj = it.next();
if(obj.equals(“ddd”)
c.add(“sdkj”);//此举就会导致并发修改异常。
}
package collectionTest;
import java.util.*;
class Student
{
private String name;
private int age;
public Student(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int age()
{
return age;
}
public String toString(){
return "["+name+","+age+"]";
}
}
public class ArrayListTest {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList<Student> al = new ArrayList<Student>();
al.add(new Student("zhangsan",20));
al.add(new Student("lisi",22));
al.add(new Student("wangwu",23));
for(Iterator<Student> it = al.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}
Collection 的子类特点
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|--Set:元素不能重复,无序。
List:特有的常见方法:有一个共性特点就是都可以操作角标。
1,添加
voidadd(index,element);
voidadd(index,collection);
2,删除;
Objectremove(index):
3,修改:
Objectset(index,element);
4,获取:
Objectget(index);
int indexOf(object);
int lastIndexOf(object);
ListsubList(from,to);
5,list集合支持列表迭代器ListIterator:
Iterator在迭代时,只能对元素进行获取(next())和删除(remove())的操作。
对于 Iterator 的子接口ListIterator在迭代list集合时,还可以对元素进行添加
(add(obj)),修改set(obj)的操作。listIterator可以在遍历过程中实现对集合元素的曾删改查。
listIterator的方法如下:
void | |
boolean | hasNext() |
boolean | hasPrevious() |
next() | |
int | nextIndex() |
previous() | |
int | previousIndex() |
void | remove() |
void |
List
特点:元素有序,集合中的元素可以重复,因为有索引。
List特有的方法:
有一个共性特点就是都可以操作角标。
1,添加
voidadd(int index,E element);
voidadd(int index,collection c);
2,删除;
Objectremove(int index):
3,修改:
Objectset(int index,E element);
4,获取:
Objectget(int index);
int indexOf(object);
int lastIndexOf(object);
ListsubList(int from,int to);包含头不包含尾
子类特点:
ArrayList:用数组实现,线程不同步。查询速度快,增删速度稍慢。
LinkedList:链表实现,线程不同步,查询速度慢,增删速度快。
Vector:数组实现,线程同步。效率低,一般不使用。
LinkedList
特有方法:
addFirst(); offerFirst();
addLast(): offetLast();
getFirst();.//获取但不移除,如果链表为空,抛出NoSuchElementException.
peekFirst();//获取但不移除,如果链表为空,返回null.
getLast();
peekLast():
removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException.
pollFirst();//获取并移除,如果链表为空,返回null.
removeLast();
pollLast();
Set
Set:元素不可以重复,是无序。
Set接口中的方法和Collection一致。
|--HashSet:内部数据结构是哈希表,是不同步的。
保证该集合的元素唯一性:
通过hashCode()和equals()方法来完成对象唯一性的。
如果哈希值不同,那么不用equals()方法判断是否是同一个对象,就直接存储到哈希表中。
如果哈希值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode()方法和equals()方法。
注意:覆盖public int hashCode()和booleanequals(Object object)一定要要与父类的方法相同,否则不是覆盖,而是重新定义了一个新函数。
|--TreeSet:可以对Set集合中的元素进行排序。是不同步的。
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,元就需要实现Comparable接口。覆盖compareTo()方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare()方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
方法代码演示:
1、自定义Person类使其具有比较性
package collectionTest;
public class Person implements Comparable<Person>{//实现Comparable接口,是对象具有可比性
private String name;
private String sex;
private int age;
public Person(String name,String sex,int age)
{
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
//实现其中的compareTo()方法
public int compareTo(Person p) {
//比较姓名
return this.getName().compareTo(p.getName());
}
public String toString(){
return "姓名:"+this.name+" 性别:"+this.sex+" 年龄:"+this.age;
}
}
2、自定义比较器,可以在集合建立时指定比较器
package collectionTest;
import java.util.*;
public class treeSetTest {
class myComp implements Comparator//自定义比较器
{
//实现compara()方法
@Override
public int compare(Object o1, Object o2) {
//先比较姓名,姓名相同再比较年龄
// TODO Auto-generated method stub
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int equalName = p1.getName().compareTo(p2.getName()) ;
if(equalName == 0)
{
int equalSex= p1.getSex().compareTo(p2.getSex());
if(equalSex==0)
return p1.getAge()-p2.getAge();
return equalSex;
}
return equalName;
}
}
public static void main(String []args)
{
TreeSet<Person> ts = new TreeSet<Person>();
ts.add(new Person("张三","男",23));
ts.add(new Person("李四","女",21));
//ts.add(new Person("zhangsan","男",21));
//ts.add(new Person("zhangsan","男",21));
for(Iterator<Person> it = ts.iterator();it.hasNext();)
System.out.println(it.next());
}
}
泛型
1、 java升级的好处:高效、简化书写,安全。
jdk1.5出现的安全机制。优点:(1)将运行错误ClassCastException转化为编译问题,提高安全性。(2)避免了强制转换的麻烦。
泛型的应用:通过<>来定义操作的引用型数据的类型。常用于集合中,指定集合要操作的元素的类型。
1、 泛型可以作用于类上。例如:
class Util<T> {
private T t;
public setObject(T t)
{
this.t =t;
}
public getObject(T t)
{
return t;
}
}
泛型类定义的泛型在整个类中有效,泛型类的对象明确要操作的类型后,整个类中所有方法要操作的类型都确定了。
2、 泛型可以定义在方法上。如果定义方法时不知道方法要操作的类型,可以使用泛型。例如:
public <T> String getInfo(T t)
{
Return t;
}
同一个类中不同的方法定义不同的泛型,可以让同类中的方法操作不同类型。
注意:静态方法不可以访问定义在类上的泛型。因为静态优先于类存在。
3、 泛型可以定义在接口上,由实现它的类指定要操作的数据类型。例如:
interface Inter<T>
{
void show(T t);
}
class InterImleimplements Inter<String>
{
publicvoid show(String t)
{
System.out.println(t);
}
}
4、泛型的限定。
(1) <? super类名>表示要操作的类型是指定的类或者其父类
<?Extends 类名>表示要操作的类型是自定的类或者其子类