Collection
|---List(有序):通过重写equals()保证唯一性。
|---ArrayList(变长数组):查询效率高,更新效率低。线程不同步
|---LinkedList(链表):更新效率高,查询效率低。
|---Vector(数组):线程同步,效率低,被ArrayList取代。
|---Set(唯一)
|---HashSet(哈希表):重写hashCode()和equals()保证唯一性。
|---TreeSet(二叉树):通过让元素具备比较性或让集合具备比较性保证唯一性和排序。
Map
|---HashMap(哈希表):允许使用null键null值,线程不同步,效率高。
|---TreeMap(二叉树):可以按键排序,不同步。
|---HashTable(二叉树):不允许使用null键null值,线程同步,效率低。
共性方法(关于集合)
Iterator迭代器
由于Collection子接口下有的有索引有的没索引,不能像数组循环一样获取元素,因此必须有hasNext()和next(),两个方法只有一起使用时才有意义,因此将其封装成Collection的内部类,修饰为private并对外提供获取内部类对象的接口iterator(),返回类型是Iterator。比喻:Collection接口是娃娃机,Iterator是娃娃机的夹子,娃娃机夹子有抓取娃娃的操纵杆next()。
迭代器示例
Iterator it = al.iterator();
while(it.hasNext())
{
sop(it.next());
}
注意
在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常,所以只能通过迭代器的方法操作元素。
List接口
增:add(index,ele)、addAll(index,Collection)
删:remove(index)
改:set(index,ele)
查:get(index)、indexOf(ele)、subList(from,to)、listIterator()
ListIterator迭代器
ListIterator相较于Iterator迭代器的作用:由于List集合有索引,因此可在迭代的同时使用ListIterator迭代器的增删改查方法对元素进行操作。方法:add(ele)、remove()、set(ele)、hasNext()、hasPrivious()。
ListIterator li = al.listIterator();
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("haha"))
li.add("hehe"); //利用迭代器进行集合的添加元素
}
LinkedList特有方法(关于收尾结点)
1.增:addFirst()、addLast()、 2.删:removeFirst()、removeLast() 3.查:getFirst()、getLast() 若集合中没有元素,会出现NoSuchElementException异常 JDK1.6出现的替代方法 1.增:offerFirst()、offerFirst() 2.删:peakFirst()、peakLast() 3.查:pollFirst()、pollLast() 若集合中没有元素,会返回null。
Set接口
HashSet保证唯一性依据:hashCode和equals()。先比较两个对象的hashCode是否相同,若不同,直接存储进集合;若相同,再用equals()比较是否是同一个对象,若不是就存储进集合,否则不存储。代码示例。
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//重写hashCode()
public int hashCode()
{
return name.hashCode()+age;
}
//重写equals()
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return name.equals(p.name) && age == p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashSetDemo
{
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("a2",12)); //重复元素
hs.add(new Person("a3",13));
for(Iterator it = hs.iterator();it.hasNext();)
{
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
TreeSet可实现元素排序,排序的两种方式
//第一种排序方式:让元素自身具备比较性,实现自然排序
import java.util.*;
class Person implements Comparable
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//重写compareTo方法
public int compareTo(Object obj)
{
if(!(obj instanceof Person))
throw new RuntimeException("不是人对象");
Person p = (Person)obj;
if(this.age > p.age)
return 1;
if(this.age == p.age) //若主要依据相同,要比较次要依据
return this.name.compareTo(p.name);
return -1;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Person("lisi01",22));
ts.add(new Person("lisi02",25));
ts.add(new Person("lisi03",22));
ts.add(new Person("lisi03",22)); //重复元素
ts.add(new Person("lisi04",23));
for(Iterator it = ts.iterator();it.hasNext();)
{
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
//第二种排序方式:让集合具备比较性
import java.util.*;
class MyComparator implements Comparator
{
//重写compare方法
public int compare(Object o1,Object o2)
{
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int num = p1.getName().compareTo(p2.getName());
if(num == 0) //若主要依据相同,要比较次要依据
return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));
return num;
}
}
class TreeSetDemo1
{
public static void main(String[] args)
{
//传入比较器对象使集合具备比较性
TreeSet ts = new TreeSet(new MyComparator());
ts.add(new Person("lisi01",22));
ts.add(new Person("lisi02",25));
ts.add(new Person("lisi03",22));
ts.add(new Person("lisi03",22)); //重复元素
ts.add(new Person("lisi04",23));
for(Iterator it = ts.iterator();it.hasNext();)
{
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}
作用
- 将运行时期出现的问题ClassCastException转移到了编译时期,方便于程序员解决问题。
- 避免了强制转换麻烦。
- 一般在集合类中使用。
import java.util.*;
class GenericDemo
{
public static void main(String[] args)
{
//定义时就明确了要操作的类型
ArrayList<String> al = new ArrayList<String>();
//只能操作String类型
al.add("abc01");
al.add("abc02");
al.add("abc03");
for(Iterator<String> it = al.iterator();it.hasNext();)
{
String s = it.next();
System.out.println(s);
}
}
}
泛型类
使用场景:当类的对象要操作的类型一确定,成员方法操作的类型就明确,就可定义泛型类。
/*
//泛型前做法
class Tool
{
private Object obj;
public void setObject(Object obj)
{
this.obj = obj;
}
public Object getObject()
{
return obj;
}
}
*/
//泛型类
class Utils
{
private T t;
public void setObject(T t)
{
this.t = t;
}
public T getObject()
{
return t;
}
}
class GenericDemo2
{
public static void main(String[] args)
{
//泛型前做法
// Tool t = new Tool();
// t.setObject(new String("abc"));
// String s = (String)t.getObject(); //需要转型
// System.out.println(s);
//泛型做法
Utils u = new Utils();
u.setObject(new String("abc"));
String s = u.getObject(); //无需转型
System.out.println(s);
}
}
泛型方法
使用场景:为了让类中的不同方法可以操作不同类型,就可以将泛型定义在法上,类似于重载。
class Demo
{
public void show(T t) //跟随类的泛s型
{
System.out.println("show:"+t);
}
public void print(Q q) //方法上的泛型
{
System.out.println("print:"+q);
}
}
class GenericDemo3
{
public static void main(String[] args)
{
Demo d = new Demo(); //指定操作的类型是Integer
d.show(new Integer(3));
//d.show("abc"); //编译出错,show()参数类型只能是Integer
d.print(3); //print()参数类型任意
d.print("abc");
}
}
静态方法的泛型只能定义在方法上,因为静态比对象先加载。
泛型限定
1. 泛型的限定:? 通配符,代表任意类型
2. 泛型限定上限: extends E> 接收E或者E的子类型
3. 泛型限定下限: super E>> 接收E或者E的父类型
//泛型限定上限
import java.util.*;
class GenericDemo4
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new Comp());
ts.add(new Person("lisi1"));
ts.add(new Person("lisi2"));
ts.add(new Person("lisi3"));
TreeSet ts1 = new TreeSet(new Comp());
ts1.add(new Student("zhang1"));
ts1.add(new Student("zhang2"));
ts1.add(new Student("zhang3"));
print(ts);
print(ts1);
}
//泛型限定,只可以接收Person及其子类对象
public static void print(TreeSet extends Person> al)
{
for(Iterator extends Person> it = al.iterator();it.hasNext();)
{
//只能调用父类中的方法
System.out.println(it.next().getName());
//it.next().showName(); //编译出错,无法使用子类特有方法
}
}
}
class Person
{
private String name;
Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
class Student extends Person
{
Student(String name)
{
super(name);
}
public void showName()
{
System.out.println(getName());
}
}
//比较器泛型使用,可以比较Person和Person子类
class Comp implements Comparator<Person>
{
public int compare(Person p1,Person p2)
{
//只能用父类方法
return p1.getName().compareTo(p2.getName());
}
}
//泛型限定下限
import java.util.*;
import stu.love.v.Demo11;
//父类的比较器
class CompareByAge implements Comparator
{
public int compare(Person s1,Person s2)
{
int num = new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
if(num==0)
return s1.getName().compareTo(s2.getName());
return num;
}
}
/*// 子类 特殊的 比较器 Student
class ComByAge implements Comparator
{
public int compare(Student s1,Student s2)
{
int num = new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
if(num==0)
return s1.getName().compareTo(s2.getName());
return num;
}
}
// 子类 特殊的 比较器 Teacher
class ComByAge2 implements Comparator
{
public int compare(Teacher s1,Teacher s2)
{
int num = new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
if(num==0)
return s1.getName().compareTo(s2.getName());
return num;
}
}*/
class Demo13
{
//TreeSet(Comparator super E> comparator) 定义比较器时,可以是E类型,还可以是E的父类型,E在创建集合对象时确定
public static void main(String[] args)
{
TreeSet t1 = new TreeSet(new CompareByAge());
t1.add(new Student("zhaosi",23));
t1.add(new Student("lisi",25));
t1.add(new Student("wangwu",20));
TreeSet t2 = new TreeSet(new CompareByAge());
t2.add(new Teacher("wang",38));
t2.add(new Teacher("lilaoshi",48));
t2.add(new Teacher("zhanglaoshi",58));
}
}
存储键值对,一个键对应一个值,当后添加的键与之前的键相同时,后添加的元素会覆盖之前的元素。
增:put(key,value)、putAll(Map)
删:remove(key)、clear()
获取:size()、get(key)、values()、entrySet()、keySet()
判断:isEmpty()、containsKey(key)、containsValue(value)
获取元素的两种方式:keySet和entrySet()
//keySet()和entrySet()用法案例
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("02","lisi2");
map.put("01","lisi1");
map.put("03","lisi3");
map.put("04","lisi4");
//1,通过keySet获取键的集合
Set<String> keySet = map.keySet();
for(Iterator<String> it = keySet.iterator();it.hasNext();)
{
//取出一个键
String key = it.next();
//通过键获取值
System.out.println(key+":"+map.get(key));
}
//2,通过entrySet获取映射关系集合
SetString,String>> entrySet = map.entrySet();
for(IteratorString,String>> it1 = entrySet.iterator();it1.hasNext();)
{
//取出一个映射关系
Map.Entry<String,String> me = it1.next();
//通过映射关系获取键
String key = me.getKey();
//通过映射关系获取值
String value = me.getValue();
System.out.println(key+":"+value);
}
}
}
/*
Map集合一键一值用例
"yure" Student("01","zhangsan")
"yure" Stduent("02","lisi")
"jiuye" Student("01" "wangwu")
"jiuye" Student("02" "zhaoliu")
即一对多关系,由于Map是一对一关系,后会覆盖前,
因此要将一对多化解为一对一:将值存储在集合中。
*/
import java.util.*;
class MapDemo5
{
public static void main(String[] args)
{
//预热班
List yure = new ArrayList();
yure.add(new Student("01","zhangsan"));
yure.add(new Student("02","lisi"));
//就业班
List jiuye = new ArrayList();
jiuye.add(new Student("01","wangwu"));
jiuye.add(new Student("02","zhaoliu"));
//学校
HashMap> czbk = new HashMap>();
czbk.put("yure",yure); //学校有预热班和就业班
czbk.put("jiuye",jiuye);
//遍历czbk集合,获取所有教室
for(Iterator it = czbk.keySet().iterator();it.hasNext();)
{
String roomName = it.next(); //获取一个键(教室名称)
List room = czbk.get(roomName); //通过教室名称获取学生集合
System.out.println(roomName);
getInfos(room); //输出每个学生的信息
}
}
//遍历list集合中每个学生的信息
public static void getInfos(List list)
{
for(Iterator it = list.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}
class Student
{
private String id;
private String name;
Student(String id,String name)
{
this.id = id;
this.name = name;
}
public String toString()
{
return id+name;
}
}
作用:由于List集合不能排序,Collections工具类提供了对List集合进行排序的方法和其他对集合进行操作的方法。