------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
Collection
为什么会出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对
象最常用的一种方式。
数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
数组存储对象的话,只能存储同一种类型的对象
集合框架图
为什么会出现这么多的容器?
因为每一个容器对数据的存储方式都有不同。也就是数据结构不同。。
List:元素是有序的,元素可以重复。因为该集合体系有索引。
ArrayList:底层的数据结构式数组结构。特点:查询速度快,但是增删稍慢,线程不同步(一般情况下选ArrayList,
因为实际开发中设计增删的一般远远少于查询)
LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢
Vector:底层是数组结构,线程同步,被ArrayList替代了(Vector支持枚举)
Set:元素是无序的,元素不可以重复。
List有其特有的迭代器:ListIterator。ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常,以,
在迭代器时,只能用迭代器的方法操作原始,可是Iterator方法是有限的,只能对元素进行判读,取出,删除的操作
,如果想要其他的操作,如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。
Vector枚举就是Vector特有的取出方式,发现枚举和迭代器很像,其实枚举和迭代器是一样的。因为枚举的名称以及
方法的名称都过长。所以被迭代器取代了。
Vector 代码:
//创建Vector容器
Vector vt = new Vector();
//添加元素
vt.add("00");
vt.add("01");
vt.add("03");
vt.add("04");
//枚举迭代
Enumeration en = vt.elements();
while(en.hasMoreElements()){
sop(en.nextElement());
}
List练习代码:
import java.util.*;
public class ListDemo {
public static void main(String args[]){
//创建List集合
List list = new ArrayList();
//添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//取出元素第一种方式 for循环
for(int i = 0 ; i < list.size(); i++){
System.out.println(list.get(i));
}
//取出元素第二种方式,迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//list特有的迭代方式ListIterator
ListIterator lit = list.listIterator();
while(it.hasNext()){
System.out.println(lit.next());
}
//Vector特有的取出方式:枚举
Vector ve = new Vector();
ve.addAll(list);
//枚举
Enumeration enu = ve.elements();
while(enu.hasMoreElements()){
System.out.println(enu.nextElement());
}
}
}
Linkedlist
Linkedlist特有方法:
1、增
addFirst();
addLast();
2、获取
//获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
getFirst();
getLast();
3、删
//获取元素,并删除元素。如果集合中没有元素,会出现NoSuchElementException
removeFirst();
removeLast();
在JDK1.6以后,出现了替代方法。
1、增
offFirst();
offLast();
2、获取
//获取元素,但是不删除。如果集合中没有元素,会返回null。
peekFirst();
peekLast();
3、删
//获取元素,并删除元素。如果集合中没有元素,会返回null。
pollFirst();
pollLast();
用LinkedList模仿一个堆栈
import java.util.*;
//测试类
public class StackDemo {
public static void main(String[] args) {
Stack st = new Stack();
st.myAdd("s1");
st.myAdd("s2");
st.myAdd("s3");
st.myAdd("s4");
st.myAdd("s5");
while(!st.isEmpty()){
System.out.println(st.myGet());
}
}
}
//堆栈类
class Stack{
//定义一个私有的LinkedList
private LinkedList ll;
//一创建对象,对象就包含一个Linkedlist对象
Stack(){
ll = new LinkedList();
}
//将元素插入到列表的开头
public void myAdd(Object obj){
ll.addFirst(obj);
}
//移除并返回列表的第一个元素
public Object myGet(){
return ll.removeFirst();
}
//判断集合是否为空
public boolean isEmpty(){
return ll.isEmpty();
}
}
用LinkedList模仿一个队列
代码:
import java.util.*;
//测试类
public class StackDemo {
public static void main(String[] args) {
Stack st = new Stack();
st.myAdd("s1");
st.myAdd("s2");
st.myAdd("s3");
st.myAdd("s4");
st.myAdd("s5");
while(!st.isEmpty()){
System.out.println(st.myGet());
}
}
}
//堆栈类
class Stack{
//定义一个私有的LinkedList
private LinkedList ll;
//一创建对象,对象就包含一个Linkedlist对象
Stack(){
ll = new LinkedList();
}
//将元素插入到列表的开头
public void myAdd(Object obj){
ll.addFirst(obj);
}
//移除并返回列表的第一个元素
public Object myGet(){
return ll.removeFirst();
}
//判断集合是否为空
public boolean isEmpty(){
return ll.isEmpty();
}
}
队列:先进先出,如同一个水管
package com.itheima;
import java.util.*;
//测试类
public class QueDemo {
public static void main(String args[]){
Que q = new Que();
q.myAdd("j1");
q.myAdd("j2");
q.myAdd("j3");
q.myAdd("j4");
while(!q.isEmpty()){
System.out.println(q.myGet());
}
}
}
//队列类
class Que{
//定义一个私有的LinkedList
private LinkedList ll;
//一初始化对象就有一个LinkedList
Que(){
ll = new LinkedList();
}
//每次将元素添加到列表的开头
public void myAdd(Object obj){
ll.addFirst(obj);
}
//移除并返回列表的最后一个元素
public Object myGet(){
return ll.removeLast();
}
//判断列表是否为空
public Boolean isEmpty(){
return ll.isEmpty();
}
}
ArrayList集合去重
代码:
import java.util.*;
//测试类
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList ar = new ArrayList();
ar.add(new Person1("lisi 01",23));
ar.add(new Person1("lisi 01",23));
ar.add(new Person1("lisi 02",26));
ar.add(new Person1("lisi 03",21));
ar.add(new Person1("lisi 04",22));
ar = Singe.sinElemnt(ar);
Iterator it =ar.iterator();
while(it.hasNext()){
Person1 p = (Person1)it.next();
System.out.println(p.name);
}
}
}
class Singe{
//去重的方法
public static ArrayList sinElemnt(ArrayList ar){//传入一个要去重的集合
//定义一个新集合
ArrayList myArray = new ArrayList();
Iterator it = ar.iterator();
//遍历传入的集合,并判断新集合中是否包含传入集合的每个元素,如果不包含,就把此元素添加到新集合中
while(it.hasNext()){
Object obj = it.next();
if(!myArray.contains(obj)){
myArray.add(obj);
}
}
//返回去重后的新集合
return myArray;
}
}
class Person1{
String name;
int age;
public Person1(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
//重写equals方法
public boolean equals(Object obj){
if(!(obj instanceof Person1))
return false;
Person1 p = (Person1)obj;
return this.name.equals(p.name) && this.age == p.age;
}
}
set
Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复
HashSet:底层数据结构是哈希表
HashSet是如何保证元素的唯一性的?
是通过元素的两个方法,hashCode和equals来完成的
如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals方法
HashSet判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法
但ArrayList删除和判断元素是否存在,依赖equals方法
TreeSet可以对Set集合中的元素进行排序,底层数据结构式二叉树,保证元素的唯一性依据的是compareTo方法。
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方
式也称为元素的自然顺序,或者叫做默认排序。
排序时,当主要条件相同时,一定要判断一下次要条件
代码:
import java.util.*;
//测试类
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Student("lisi01",22));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi03",24));
ts.add(new Student("lisi05",20));
ts.add(new Student("lisi05",19));
//迭代取出元素
for(Iterator it = ts.iterator();it.hasNext();){
Student st = (Student)it.next();
System.out.println(st.getName()+"...."+st.getAge());
}
}
}
//Student实现了Comparable接口
class Student implements Comparable{
private String name;
private int age;
//构造函数
public Student(String name, int age){
this.name = name;
this.age = age;
}
//get方法
public String getName() {
return name;
}
public int getAge() {
return age;
}
//复写compareTo方法
@Override
public int compareTo(Object obj) {
//类型强转
Student st = (Student)obj;
//比较年龄 主要条件
int num = new Integer(this.getAge()).compareTo(new Integer(st.getAge()));
//如果年龄相等比较姓名 次要条件
if(num == 0){
return this.getName().compareTo(st.getName());
}
//如果年龄不相等 返回年龄的比较值
return num;
}
}
TreeSet排序的第二种实现方式:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身
具备比较性。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
定义一个类,实现Comparator接口,覆盖compare方法。
代码:
import java.util.*;
//测试类
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyCompare());
ts.add(new Student("lisi01",22));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi03",24));
ts.add(new Student("lisi05",20));
ts.add(new Student("lisi05",19));
//迭代取出元素
for(Iterator it = ts.iterator();it.hasNext();){
Student st = (Student)it.next();
System.out.println(st.getName()+"...."+st.getAge());
}
}
}
//Student实现了Comparable接口
class Student implements Comparable{
private String name;
private int age;
//构造函数
public Student(String name, int age){
this.name = name;
this.age = age;
}
//get方法
public String getName() {
return name;
}
public int getAge() {
return age;
}
//复写compareTo方法
@Override
public int compareTo(Object obj) {
//类型强转
Student st = (Student)obj;
//比较年龄 主要条件
int num = new Integer(this.getAge()).compareTo(new Integer(st.getAge()));
//如果年龄相等比较姓名 次要条件
if(num == 0){
return this.getName().compareTo(st.getName());
}
//如果年龄不相等 返回年龄的比较值
return num;
}
}
//比较器 实现Comparator接口
class MyCompare implements Comparator{
//重写compare方法
@Override
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 new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
//如果名字不同返回名字的比较值
return num;
}
}
泛型
泛型:JDK1,5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。
好处:1,将运行时期出现问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时问题减少,安全。
2,避免了强制转换的麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型。其实<>就是用来接收类型的,当使用集合时,将集合中要存
储的数据类型作为参数传递到<>中即可。
泛型在集合中的应用代码:
import java.util.*;
public class GenericDemo {
public static void main(String[] args) {
//定义带泛型的集合
ArrayList<String> al = new ArrayList<String>();
//添加元素
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
//迭代输出
Iterator<String> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
泛型在比较器中的应用代码:
import java.util.*;
public class GenericDemo2 {
public static void main(String[] args) {
//定义带泛型的集合
TreeSet<Student1> ts = new TreeSet<Student1>(new Comp());
ts.add(new Student1("xiaox1",21));
ts.add(new Student1("xiaox2",22));
ts.add(new Student1("xiaox3",24));
ts.add(new Student1("xiaox4",28));
ts.add(new Student1("xiaox5",13));
ts.add(new Student1("xiaox6",17));
//迭代输出
Iterator<Student1> it = ts.iterator();
while(it.hasNext()){
Student1 t1 = it.next();
System.out.println(t1.getName()+"..."+t1.getAge());
}
}
}
//在Comprable接口中定义泛型
class Student1 implements Comparable<Student1>{
private String name;
private int age;
public Student1(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
@Override
public int compareTo(Student1 t1) {
int num = new Integer(this.getAge()).compareTo(new Integer(t1.getAge()));
if(num == 0){
return this.getName().compareTo(t1.getName());
}
return num;
}
}
//在Comprator接口中定义泛型
class Comp implements Comparator<Student1>{
@Override
public int compare(Student1 t1, Student1 t2) {
int num = new Integer(t1.getAge()).compareTo(t2.getAge());
if(num == 0){
return t1.getName().compareTo(t2.getName());
}
return num;
}
}
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候。早期定义Object来完成扩展,现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中都有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经
固定了。
同时,为了让不同方法可以操作不同类型,而且类型还不确定,可以将泛型定义在方法上。
特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
//测试类
public class GenericClassDemo {
public static void main(String[] args) {
//测试泛型类
Demo<String> d = new Demo<String>();
d.show("哈哈");
d.print("heihei");
//测试泛型方法
Demo1 d1 = new Demo1();
d1.show("haha");
d1.print(2);
//测试泛型类和泛型方法的混合
Demo2<String> d2 = new Demo2<String>();
d2.show("你好啊");
d2.print(3);
}
}
//泛型类
class Demo<T>{
public void show(T t){
System.out.println(t);
}
public void print(T t){
System.out.println(t);
}
}
//泛型方法
class Demo1{
public<T> void show(T t){
System.out.println(t);
}
public <Q> void print(Q q){
System.out.println(q);
}
}
//泛型类和泛型方法的混合
class Demo2<T>{
public void show(T t){
System.out.println(t);
}
public<Q> void print(Q q){
System.out.println(q);
}
}
泛型定义在接口上
//泛型接口
interface Test<T>{
void show(T t);
}
//实现泛型接口的类
class Test1 <T> implements Test<String>{//第一个T代表类的泛型 第二个T代表接口的泛型
@Override
public void show(String t) {
System.out.println(t);
}
public void print(T t){
System.out.println(t);
}
}
//实现泛型接口的类继续使用泛型
class Test2 <T> implements Test<T>{//类和接口都使用泛型是要一致 不然会报错
@Override
public void show(T t) {
System.out.println(t);
}
public void print(T t){
System.out.println(t);
}
}
?通配符(或者说占位符)可以代表任意类型
泛型限定:
? extends E : 可以接受E类型或者E的子类类型,限定上限。
? super E 可以接受E类型或者E的父类型,限定下限。
?的示例代码:
import java.util.*;
public class GenericDemo3 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("li1");
al.add("li2");
al.add("li3");
al.add("li4");
al.add("li5");
ArrayList<Integer> al2 = new ArrayList<Integer>();
al2.add(1);
al2.add(2);
al2.add(3);
al2.add(4);
al2.add(5);
//传入al 泛型
print(al);
//传入 al2 泛型
print(al2);
}
public static void print(ArrayList<?> al){//使用通配符
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
? extends E示例代码:
import java.util.*;
//测试类
public class GenericDemo4 {
public static void main(String[] args) {
//泛型为父类Person的ArrayList
ArrayList <Person> al = new ArrayList<Person>();
//泛型为子类Student2 的ArrayList
ArrayList<Student2> al2 = new ArrayList<Student2>();
//泛型为子类Worker的ArrayList
ArrayList<Worker> al3 = new ArrayList<Worker>();
al.add(new Person("Person1"));
al.add(new Person("Person2"));
al.add(new Person("Person3"));
al2.add(new Student2("Student1"));
al2.add(new Student2("Student2"));
al2.add(new Student2("Student3"));
al3.add(new Worker("Worker1"));
al3.add(new Worker("Worker2"));
al3.add(new Worker("Worker3"));
//打印al
print(al);
//打印al2
print(al2);
//打印al3
print(al3);
}
public static void print(ArrayList<? extends Person> al){//使用上限为Peroson的通配符
//迭代 取出 打印
Iterator<? extends Person> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
}
}
//父类
class Person{
private String name;
public Person(String name){
this.name = name;
}
public String getName(){
return name;
}
private void show(){
}
}
//子类 Student2
class Student2 extends Person{
public Student2(String name){
super(name);
}
}
//子类 Worker
class Worker extends Person{
String name;
public Worker(String name) {
super(name);
}
}
? super E代码:
TreeSet<E> 有一个构造函数TreeSet(Comparator<? super E comparator>
示例代码:
import java.util.*;
public class GenaricDemo5 {
public static void main(String[] args) {
TreeSet<Student3> al = new TreeSet<Student3>(new Comp3());//Student3 TreeSet 传入Person3 比较器
TreeSet<Worker3> al2 = new TreeSet<Worker3>(new Comp3());//Worker3 TreeSet 传入Person3 比较器
al.add(new Student3("lisi01"));
al.add(new Student3("lisi02"));
al.add(new Student3("lisi03"));
al2.add(new Worker3("wangwu01"));
al2.add(new Worker3("wangwu02"));
al2.add(new Worker3("wangwu03"));
//迭代取出
Iterator<Student3> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
Iterator<Worker3> i = al2.iterator();
while(i.hasNext()){
System.out.println(i.next().getName());
}
}
}
//父类Person3
class Person3{
private String name;
private int age;
public Person3(String name){
this.name = name;
}
public String getName(){
return name;
}
}
//子类Student3
class Student3 extends Person3 {
public Student3(String name) {
super(name);
// TODO Auto-generated constructor stub
}
}
//子类Worker3
class Worker3 extends Person3{
public Worker3(String name) {
super(name);
// TODO Auto-generated constructor stub
}
}
//Person3 类型的比较器
class Comp3 implements Comparator<Person3> {
@Override
public int compare(Person3 o1, Person3 o2) {
return o1.getName().compareTo(o2.getName());
}
}