--------------android培训、java培训、学习型技术博客、期待与您交流! --------------
1)集合概述
作用:
面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式.
数组和集合区别:
集合:
长度可以改变
可以存储不同类型的对象
只能存储对象类型
数组:
长度固定
只能存储同一种类型的元素
可以存储基本类型,也可以存储对象类型
2)集合体系
collection
List 元素有序(存储和取出的顺序一致),元素可以重复
|--ArrayList 底层数据结构是数组,查询快,增删慢,线程不安全,效率高
|--Vector 底层数据结构是数组,查询快,增删慢,线程安全,效率低|--LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高
Set 元素无序(存储和取出顺序不一致),唯一。
|--HashSet 底层数据结构是哈希表。依次调用hashCode()和equals()保证元素的唯一性。
|--LinkedHashSet 底层数据结构是哈希表和链表。哈希表保证元素的唯一,链表保证元素的有序。
|--TreeSet 底层数据结构是二叉树。根据自然排序或者比较器的返回值是否是0,决定唯一性和排序。
public class Student implements Comparable<Student>
{
public int compareTo(Student s)
{
...
}
}
TreeSet 比较器排序: 让TreeSet集合在实例化的时候,接收一个Comparator类型的参数。
TreeSet ts = new TreeSet<Student>(new Comparator<Student>(){
public int compare(Student s1, Student s2)
{
...
}
});
枚举:
就是Vector特有的取出方式。Vector有三种取出方式。
其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。
特有方法:
addElement(obj);//添加元素,相当于add(obj);
Enumerationelements();//Vector特有取出方式(枚举)
hasMoreElements();//相当于Iterator的hasNext()方法
nextElements();//相当于Iterator的next()方法
代码示例
Vector v=new Vector();
for(Enumeration e=v.elements();e.hasMoreElements();)
{
System.out.println(e.nextElements());
}
import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo
{
public static void main(String[] args){
//创建集合对象
HashSet<Student> has = new HashSet<Student>();
//创建元素对象
Student s1 = new Student("布兰妮",30,"纽约");
Student s2 = new Student("布莱曼",39,"伦敦");
Student s3 = new Student("章子怡",32,"北京");
Student s4 = new Student("章子怡",32,"北京");
//添加元素对象到集合中
has.add(s1);
has.add(s2);
has.add(s3);
has.add(s4);
//遍历集合---迭代器
Iterator<Student> it = has.iterator();
while (it.hasNext())
{
Student s = it.next();
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getAddress());
}
System.out.println("*******************************************");
//变量集合---增强for循环
for (Student s : has )
{
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getAddress());
}
}
}
public class Student
{
private String name;
private int age;
private String address;
public Student(){
}
public Student(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age ){
this.age = age;
}
public int getAge(){
return age;
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
//生成哈希code
public int hashCode(){
return this.name.hashCode()+this.age*17+this.address.hashCode();
}
public boolean equals(Object obj){
//提高效率
if (this == obj)
return true;
//健壮性
if (!(obj instanceof Student))
{
return false;
}
//转型
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.age && this.address.equals(s.address);
}
}
TreeSet自然排序代码举例:
/*
* java.lang.ClassCastException:
* cn.itcast_03.Student cannot be cast to java.lang.Comparable
*
* 通过查看API,我们发现了这个接口就是对类进行自然排序的功能定义,我们自己定义的类必须去实现这个接口,才能进行自然排序。
*/
public class Student implements Comparable<Student> {
// 姓名
private String name;
// 年龄
private int age;
public Student() {
}
public Student(String name, int age) {
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;
}
@Override
public int compareTo(Student s) {
// 根据年龄的大小返回。
// 如果返回正数:说明大往后放
// 如果返回负数:说明小往前放
// return this.age - s.age;
// 很多时候,我们不仅仅要考虑到主要条件,
// 还需要考虑次要条件:也就是说在年龄相同的情况下,我们还需要判断姓名是否相同。
int num = this.age - s.age;
int num2 = (num == 0) ? this.name.compareTo(s.name) : num;
return num2;
}
}
import java.util.Iterator;
import java.util.TreeSet;
/*
* 需求:存储5个学生,要求按照学生的年龄排序,如果一个对象的成员变量的值都相同即为同一个对象。
*
* 类要进行排序的自然接口:Comparable
*
* TreeSet的底层数据结构是:二叉树。
* 怎么保证元素的唯一性?
* 根据compareTo()方法的返回值是否是0。
* 如果是0:说明元素已经存在。
* 如果不是0:说明元素不存在。
* 以及怎么实现数据的排序 ?
* 如果compareTo()方法的返回值是一个正数:说明添加的元素,比以前的那个元素大。
* 如果compareTo()方法的返回值是一个负数:说明添加的元素,比以前的那个元素小。
*
* 如果数据较大,就往后放。
* 如果数据较小,就往前放。
* 最后,遍历即可。
*/
public class TreeSetDemo2 {
public static void main(String[] args) {
// 创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();
// 创建元素对象
Student s1 = new Student("linqingxia", 26);
Student s2 = new Student("wangzuxian", 40);
Student s3 = new Student("yangmi", 20);
Student s4 = new Student("zhaowei", 38);
Student s5 = new Student("linqingxia", 26);
Student s6 = new Student("linen", 26);
// 添加学生
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
// 遍历数据
Iterator<Student> it = ts.iterator();
while (it.hasNext()) {
Student s = it.next();
System.out.println(s.getName() + "***" + s.getAge());
}
}
}
TreeSet比较器排序代码举例:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/*
* 需求:要求存储学生,按照学生的姓名长度排序。(排序)
* 如果成员变量的值都相同即为同一个值。(唯一)
*
* 编程信条:对修改关闭,对扩展开放。
*
* 如果两者同时都存在,以比较器的方式为主。
*
* 格式:
* new 类名或者接口名()
* {
* //重写方法
* }
*
* 一般当方法的参数是接口,并且接口中的方法不超过3个的时候,
* 我们就会采用匿名内部类的形式去体现。
*
* 这种格式体现的是一个:
* 是一个实现了指定接口的子类的匿名对象。
*
*/
public class TreeSetDemo {
public static void main(String[] args) {
// 创建集合对象
// TreeSet<Student> ts = new TreeSet<Student>();
// TreeSet(Comparator comparator)
// 不管是在调用成员方法时,还是在调用构造方法时,
// 如果你看到的参数是抽象类或者接口
// 请注意:这里传递肯定是一个具体的实现类对象。
// MyComparator my = new MyComparator();
// MyComparator2 my2 = new MyComparator2();
// TreeSet<Student> ts = new TreeSet<Student>(my2);
// 如果接口中只有一个方法,一般不在专门创建一个具体的类去做。
// 用匿名内部类实现。
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getName().length() - s2.getName().length();
int num2 = (num == 0) ? s1.getName().compareTo(s2.getName()) : num;
int num3 = (num2 == 0) ? s1.getAge() - s2.getAge() : num2;
return num3;
}
});
// 创建元素对象
Student s1 = new Student("linqingxia", 26);
Student s2 = new Student("wangzuxian", 40);
Student s3 = new Student("yangmi", 20);
Student s4 = new Student("zhaowei", 38);
Student s5 = new Student("linqingxia", 26);
Student s6 = new Student("linen", 26);
Student s7 = new Student("linqingxia", 56);
// 添加学生
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
// 遍历数据
Iterator<Student> it = ts.iterator();
while (it.hasNext()) {
Student s = it.next();
System.out.println(s.getName() + "***" + s.getAge());
}
}
}
public class Student implements Comparable<Student> {
// 姓名
private String name;
// 年龄
private int age;
public Student() {
}
public Student(String name, int age) {
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;
}
@Override
public int compareTo(Student s) {
// 姓名长度
// 主要条件
int num = this.name.length() - s.name.length();
// 次要条件
int num2 = (num == 0) ? this.name.compareTo(s.name) : num;
// 当姓名的长度和内容都相同的时候,需要在考虑年龄是否也相同。
int num3 = (num2 == 0) ? this.age - s.age : num2;
return num3;
}
}
map集合
由键值对形成的一个集合,键是唯一的。值可以重复。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。
|--HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
Map和Set很像。其实Set底层就是使用了Map集合。
Map和Collection的区别
map:1,Map是键值对形式的集合,数据是成对出现的。2,键是唯一的。
Collection:1,是单列形式的集合,数据是单一出现的。2,Collection的儿子Set的元素是唯一的。
Map集合的两种取出方式
a、Set<K> keySet():将Map中所以的键存入到Set集合。因为Set具备迭代器。所以可以通过迭代方式取出所以键的值,再通过get方法。获取每一个键对应的值。
b、Set<Map.Entry<K,V>> entrySet():将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是:Map.Entry其实,Entry也是一个接口,它是Map接口中的一个内部接口。
keySet方式代码
/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。
思路:1、描述学生类
2、定义一个Map集合,存储学生对象和地址值
3、获取Map中的元素
*/
import java.util.*;
//描述学生类
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//复写hashCode
public int hashCode()
{
return name.hashCode()+age*33;
}
//复写equals,比较对象内容
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s=(Student)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
//复写compareTo,以年龄为主
public int compareTo(Student c)
{
int num=new Integer(this.age).compareTo(new Integer(c.age));
if(num==0)
{
return this.name.compareTo(c.name);
}
return num;
}
//复写toString,自定义输出内容
public String toString()
{
return name+"..."+age;
}
}
class HashMapTest
{
public static void main(String[] args)
{
HashMap<Student,String > hm=new HashMap<Student,String >();
hm.put(new Student("zhangsan",12),"beijing");
hm.put(new Student("zhangsan",32),"sahnghai");
hm.put(new Student("zhangsan",22),"changsha");
hm.put(new Student("zhangsan",62),"USA");
hm.put(new Student("zhangsan",12),"tianjing");
keyset(hm);
}
//keySet取出方式
public static void keyset(HashMap<Student,String> hm)
{
Iterator<Student> it=hm.keySet().iterator();
while(it.hasNext())
{
Student s=it.next();
String addr=hm.get(s);
System.out.println(s+":"+addr);
}
}
}
Map.Entry方式代码
class HashMapTest
{
public static void main(String[] args)
{
HashMap<Student,String > hm=new HashMap<Student,String >();
hm.put(new Student("zhangsan",12),"beijing");
hm.put(new Student("zhangsan",32),"sahnghai");
hm.put(new Student("zhangsan",22),"changsha");
hm.put(new Student("zhangsan",62),"USA");
hm.put(new Student("zhangsan",12),"tianjing");
entryset(hm);
}
//entrySet取出方式
public static void entryset(HashMap<Student,String> hm)
{
Iterator<Map.Entry<Student,String>> it=hm.entrySet().iterator();
while(it.hasNext())
{
Map.Entry<Student,String> me=it.next();
Student s=me.getKey();
String addr=me.getValue();
System.out.println(s+":::"+addr);
}
}
}
Map应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。
/*
map集合被使用是因为具备映射关系。
以下是班级对应学生,而学生中学号对应着姓名的映射关系:
"yureban" Student("01" "zhangsan");
"yureban" Student("02" "lisi");
"jiuyeban" "01" "wangwu";
"jiuyeban" "02" "zhaoliu";
就如同一个学校有多个教室。每一个教室都有名称。
*/
import java.util.*;
class MapExpandKnow
{
public static void main(String[] args)
{
//预热班集合
HashMap<String,String> yureban=new HashMap<String,String>();
//就业班集合
HashMap<String,String> jiuyeban=new HashMap<String,String>();
//学校集合
HashMap<String,HashMap<String,String>> czbk=new HashMap<String,HashMap<String,String>>();
//学校中班级集合和名称的映射
czbk.put("yureban",yureban);
czbk.put("jiuyueban",jiuyeban);
//预热班级中学号与姓名的映射
yureban.put("01","zhangsan");
yureban.put("02","lisi");
//就业班级中学号与姓名的映射
jiuyeban.put("01","wangwu");
jiuyeban.put("02","zhouqi");
//直接显示全部学生信息
getAllStudentInfo(czbk);
}
//定义一个方法获取全部学生信息,包括在哪个班级,叫什么名字,学号多少
public static void getAllStudentInfo(HashMap<String ,HashMap<String,String>> hm)
{
for (Iterator<String> it=hm.keySet().iterator();it.hasNext() ; )//用keySet取出方式
{
String s= it.next();//班级名称
System.out.println(s+":");
HashMap<String,String> stu=hm.get(s);//班级集合
getStudentInfo(stu);
}
}
//获取班级中学生的信息,包括姓名和学号
public static void getStudentInfo(HashMap<String,String> hm)
{
for (Iterator<String> it=hm.keySet().iterator();it.hasNext() ; )
{
String key=it.next();//学号
String value=hm.get(key);//姓名
System.out.println(key+"..."+value);
}
}
}