Collection的体系简单介绍:
Collection
|--List: 有序的,带索引的,通过索引就可以精确得操作集合中的元素,元素是可以重复的。
List提供了增删改查动作
增加add(element) add(index,element);
删除remove(element) remove(index)
修改set(index,element)
查询get(index)
|--Vector:可以增长的数组结构,同步的,效率很低,已被Array1List替代。
|--ArrayList:是数组结构,长度是可变的(原理是创建新数组+复制数组),查询速度很快,增删较慢,是不同步的。
|--LinkedList:是链表结构,是不同步的,增删的速度很快,查询速度较慢。
可用于实现堆栈,队列。
List可以存储重复元素的,如果需求中要求容器中的元素必须保证唯一性
|--Set:不包含重复元素的集合,不保证顺序。而且方法和Collection一致。Set集合取出元素的方法只有一种:迭代器。
|--HashSet:哈希表结构,不同步,保证元素唯一性的方法依赖于:hasCode(),equals()方法。查询速度快。
|--TreeSet:可以对Set集合中的元素进行排序,使用的是二叉树结构,如何保证元素唯一性的呢?
使用的对象比较方法的结果是否为0,是0,视为相同元素不存。
元素的排序比较有两种方式
1,元素自身具备自然排序,其实就是实现了Comparable接口重写了compareTo方法。
如果元素自身不具备自然排序,或者具备的自然排序不是所需要的。这是只能用第二方式。
2,比较器排序,其实就是在创建TreeSet集合时,在构造函数中指定具体的比较方式。
需要定义一个类实现Comparator接口,重写compare方法。
小结:在往集合中存储对象时,通常该对象都需要覆盖hashCode,equals方法
同时实现Comparable接口,建立对象的自然排序。通常还有一个方法也会复写toString()
Student类的编写的加强版:
public class Student implements Comparable {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 重写hashCode方法,建立Student对象的hash值算法内容
* 通过学生对象特有数据姓名和年龄值来算出hash值。
*/
/*@Override
public int hashCode() {
return name.hashCode()+age*24;//乘以一个随意的数,避免hash冲突
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(!(obj instanceof Student)){
throw new ClassCastException("类型错误");
}
Student stu =(Student)obj;
return this.name.equals(stu.name)&&this.age==stu.age;
}*/
/**
* 通过 alt+shift+s快捷键,直接创建重写的 equals和hasCode方法
*/
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
/**
* 重写了comparaTo方法,建立学生的自然排序(对象的默认排序方式)
* 按照学生的年龄排序
*/
@Override
public int compareTo(Object o) {
if(!(o instanceof Student)){
throw new ClassCastException();
}
Student stu= (Student) o;
/* if(this.age>stu.age){
return 1;
}
if(this.age<stu.age){
return -1;
}*/
/*
* 注意:在比较时,必须明确主次,主要条件相同,继续比较次要条件。
*/
int temp=this.age-stu.age;
return temp==0?this.name.compareTo(stu.name):temp;
}
}
Set接口:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import domin.Student;
public class SetDmeo {
public static void main(String[] args) {
Set set=new HashSet();
/* 去除集合中重复的元素
set.add("abc1");
set.add("abc2");
set.add("abc1");
set.add("abc1");
set.add("abc3");
set.add("abc2");
set.add("abc4");*/
set.add(new Student("lisi2",22));
set.add(new Student("lisi1",23));
set.add(new Student("lisi1",23));
set.add(new Student("lisi2",22));
/*
* 为什么学生对象没有保证唯一性呢?
* 通过对哈希表的分析
* 存储元素时,先调用了元素对象的hashCode(),而每个学生对象都是新建立的对象
* 所hashCode值都是不相同,也就不需要判断equals了。
* 想要按照需求同姓名同年龄来保证学生对象的唯一性,怎样解决呢?
* 不能使用Object中hashCode方法,需要重新定义hashCode的算法内容。
* 简单说:重写hashCode方法
*/
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
TreeSet集合
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import domin.Student;
public class TreeSetDemo {
public static void main(String[] args) {
//演示TreeSet
Set set= new TreeSet();
/* set.add("ccc");
set.add("bbb");
set.add("aaa");
set.add("ddd");*/
/**
* TreeSet的add方法内部最终实现。
* 需要将元素转成Comparable类型,为什么?因为这个类型具备排序的能力。
* 这个类型中有一个专门为排序提供了一个compareTo方法。
* 如果让学生具备比较排序的功能,需要让学生扩展功能,实现Comparable接口。
*/
set.add(new Student("lisi1",21));
set.add(new Student("lisi3",22));
set.add(new Student("lisi4",24));
set.add(new Student("lisi6",22));
set.add(new Student("lisi3",23));
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
ComparatorByName
import java.util.Comparator;
import domin.Student;
public class ComparatorByName implements Comparator{
@Override
public int compare(Object o1, Object o2) {
// 因为要比较的是学生对象的姓名,所以向下转型Student对象。
Student s1= (Student)o1;
Student s2= (Student)o2;
//先比较主关键字年龄。
int temp =s1.getName().compareTo(s2.getName());
//后比较次关键字
return temp==0 ? s1.getAge()-s2.getAge():temp;
}
}
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import comparator.ComparatorByName;
import domin.Student;
public class TreeSetDemo2 {
public static void main(String[] args) {
//在创建TreeSet集合对象时明确比较器。
Set set= new TreeSet(new ComparatorByName());
/*
* 想要按照学生的姓名排序,说明学生中的自然排序不是岁需要的
* 这时只能使用比较器。ComparatorByName
*/
set.add(new Student("lisi1",21));
set.add(new Student("lisi3",22));
set.add(new Student("lisi4",24));
set.add(new Student("lisi6",22));
set.add(new Student("lisi3",23));
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
TreeSetTest
练习:要对字符串进行长度(由短到长)排序。
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import comparator.ComparatorByLength;
public class TreeSetTest {
public static void main(String[] args) {
/*
* 练习:要对字符串进行长度(由短到长)排序。
* 思路:
* 1,字符串之所以能排序,因为是已经实现Comparable接口重写compareTo方法
* 建立了字符串的自然排序。
* 2,但是自然排序不是需求中所需要的,
* 只能使用比较器,需要自定义一个比较器。
*/
Set set =new TreeSet(new ComparatorByLength());
set.add("abc");
set.add("lollol");
set.add("dd");
set.add("cc");
set.add("xiao");
set.add("b");
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
import java.util.Comparator;
public class ComparatorByLength implements Comparator {
@Override
public int compare(Object o1, Object o2) {
String s1 =(String)o1;
String s2 =(String)o2;
int temp =s1.length()-s2.length();
return temp==0?s1.compareTo(s2):temp;
}
}
LinkedHashSetDemo
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetDemo {
public static void main(String[] args) {
/*
* 提高唯一性元素的查询效率,还想有序,可使用HashSet的子类LinkedHashSet
*/
Set set =new LinkedHashSet();
set.add("cbcd");
set.add("aahah");
set.add("baj");
set.add("dab");
for (Iterator it = set.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}
foreach循环
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class ForeachDemo {
public static void main(String[] args) {
/*
* foreach:其实就是增强for循环。
* 格式:
* for(元素的数据类型 变量 :Collection集合or数组){}
* 用于遍历Collection和数组。通常只能遍历元素,不要在遍历的过程中做对集合元素的操作。
*
* 与之前的for循环的区别
* 注意:新for循环必须有被遍历的目标,目标只能是Collection或者数组。
* 建议:遍历数组时,如果仅为遍历,可以使用增强for,如果对数组的元素进行操作,使用之前的for循环可以通过角标实现
*/
List list =new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
// for (Iterator it = list.iterator(); it.hasNext();) {
// System.out.println(it.next());
// }
for(Object obj :list){//简化
System.out.println(obj);
}
}
}
枚举Enumeration
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class EnumerationDemo {
public static void main(String[] args) {
Vector v =new Vector();
v.addElement("abc1");
v.addElement("abc2");
v.addElement("abc3");
v.addElement("abc4");
//枚举:名称太长,郁郁而终
for(Enumeration en = v.elements(); en.hasMoreElements();){
System.out.println("enumeratiom "+en.nextElement());
}
for (Iterator it = v.iterator(); it.hasNext();) {
System.out.println("iterator :"+it.next());
}
for(Object obj : v){
System.out.println(obj);
}
}
}
看集合对象的小技巧
看集合对象的小技巧 :
集合分体系。List Set
子类对象的后缀名是所需体系,前缀名是数据结构名称
List:新出的子类都是以List结尾,通常都是非同步的。
|--ArrayList 看到array,就知道是数组,查询速度快。
|--LinkedList 看到link,就知道链表,增删速度快。
Set:
|--HashSet:看到hash,就知道是哈希表,查询速度快,并想到元素唯一,通过hashCode(),equal方法保证唯一性
|--TreeSet:看到tree,就知道是二叉树,可以排序,排序想到Comparable-compareTo Comparator--compare方法