黑马程序员
集合类:
对象用于封装特有数据,对象如果个数众多且需要存储,就使用集合容器进行存储。
集合的特点:
1.用于存储对象的容器。
2.集合的长度是可变的。
3.集合中不可以存储基本数据。
集合容器因为内部的数据结构不同,有多种具体容器.
不断向上抽取,就形成类集合框架Collection.
1.添加
boolean add(Object obj)
boolean addAll(Collection coll)
2.删除
boolean remove(Object obj)
boolean removeAll(Object obj)
void clear();
3.判断
boolean contains(Object obj)
boolean comtainsAll(Object obj)
boolean isEmpty();
4.获取
int size();
集合中引用的都是地址。
迭代器:不同集合数据结构不同,所以取出动作细节也不同,但都具备共性内容:判断和取出。
所以将共性内容抽取出来形成迭代器。
所以迭代器就是集合取出元素的方式。
在迭代器循环中,允许对集合进行删除操作,不允许进行增加操作。
步骤:1.用集合的iterator(),获取一个迭代器。
2.用迭代器的next()方法获取下一个元素。
3.用迭代器的hasNext()判断是否还有下个元素。
以下代码演示Collection的基本操作
import java.util.*; class ACollectionDemo{ public static void main(String[] args) { //创建一个集合容器,使用Collection接口的子类,ArrayList ArrayList a1 = new ArrayList(); //定义集合 ArrayList a2 = new ArrayList(); //1.添加元素 a1.add("java01"); //a1.add(Object obj)) a1.add("java02"); a1.add("java03"); a1.add("java04"); a2.add("java01"); //a2.add(Object obj)) Iterator it = a1.iterator(); //获取迭代器,用于取出容器a1中的元素 while (it.hasNext()){ // it.hasNext 判断容器中是否还有下个元素 sop(it.next()); //获取容器中的下个元素 } //打印集合 sop("集合a1:"+a1+" 集合a2:"+a2); //2.获取个数,集合长度。 sop("a1的size:"+a1.size()); //3.删除元素。 a1.remove("java02"); //al.clear(); 清空集合。 sop(a1); //4.判断元素 sop("java03是否在集合内:"+a1.contains("java03")); sop("集合是否为空:"+a1.isEmpty()); //5.操作 a1.retainAll(a2); //取a1和a2交集赋予a1 sop("集合a1:"+a1); //a1.removeAll(a2); //从a1中删除a1与a2的交集 //sop("集合a1:"+a1); } public static void sop(Object obj){ //静态函数 System.out.println(obj); } }
运行结果
集合类的主要分类为List、Set、Map
List:元素有序,元素可以重复
|--ArrayList:底层的数据结构使用的数组结构 特点:查询速度快,但是但增删慢,线程不同步。
|--LinkList:底层使用的链表结构 特点:查询慢,但增删快
|--Vector:底层使用的数组结构,线程同步 被ArrayList替换 特点:增删,查询都很慢
List特有方法:(凡可以操作角标的方法都是该体系的特与方法)
增:
add(index,element)
addAll(index,Collection)
删;
remove(index);
改:
set(index,element);
查:
get(index);
subList(from,to);
listIterator();
indexOf(element);
List集合特有的迭代器:ListIterator是Iterator的子接口,可以在迭代中对集合进行增、删、改,和倒序遍历操作。
在迭代过程中,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。
ArrayList因为底层的数据结构使用的数组结构,所以可以用循环对其进行操作。
以下代码演示ArrayList的常用方法
import java.util.*; class BArrayList { public static void main(String[] args){ ArrayList a1 = new ArrayList(); //定义集合 a1.add("java01"); //添加元素 a1.add("java02"); a1.add("java03"); a1.add("java04"); sop("原集合:"+a1); a1.add(1,"java09"); //在指定位置添加元素 sop("添加元素后集合a1:"+a1); a1.remove(2); //在指定位置删除元素 sop("删除指定元素后集合a1:"+a1); a1.set(2,"java07"); //更改指定位置元素 sop("更改2号位置元素后集合a1:"+a1); sop("get(0):"+a1.get(0)); //获取指定位置元素 for (int x=0;x<a1.size();x++){ //通过for循环获取所有元素 sop("a1("+x+"):"+a1.get(x)); } sop("--------------------------"); for (Iterator it=a1.iterator();it.hasNext() ; ){//通过迭代器方式获取所有元素 sop(it.next()); } sop("index="+a1.indexOf("java01")); List sub = a1.subList(1,3); //获取子集合包含开始指针,不包含结束指针。 sop("sub="+sub); sop("--------------------------"); sop("原集合:"+a1); ListIterator li = a1.listIterator(); while (li.hasNext()){ //通过循环将集合中的"java09"改为"java006" Object obj = li.next(); if (obj.equals("java09")) //判断取出的元素是否为java09 { li.set("java006"); //将元素改为java006 } } sop(a1); } public static void sop(Object obj){ //定义打印方法 System.out.println(obj); } }
运行结果
ArrayList集合的简单应用
需求:
去除ArrayList集合中的重复元素
思路:
定义一个临时容器,将ArrayList中的每个元素存入临时容器中
每次存入元素时先判断临时容器中是否有该元素。
步骤:
1.导包,在主函数中创建原容器并存入元素
2.创建一个取单的对象,在其中创建取单的方法
3.在主函数中调用对象中取单方法(把原容器传入调用的对象)
4.将取单完成的新容器传给原容器,并打印
import java.util.*; public class BArrayListTest{ public static void main(String[] args) { ArrayList a1 = new ArrayList (); //定义原容器,并向里面存入元素 a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java01"); a1.add("java02"); a1.add("java03"); a1.add("java04"); a1.add("java05"); a1.add("java01"); sopCH.sop("原集合"+a1); a1 = ArrayTool.SingleElement(a1); //调用编写的去重复元素静态方法 sopCH.sop("去除重复元素后集合:"+a1); } } class sop{ public static void sop(Object obj){ System.out.println(obj); } } class ArrayTool{ //定义一个工具类 static ArrayList a2 = new ArrayList (); //定义一个新集合a2用于存储去掉重复元素后的集合 public static ArrayList SingleElement(ArrayList a1){ //定义去重复元素的静态方法(方便通过类名调用) for (int x=0;x<a1.size() ;x++ ){ //通过for循环遍历集合a1 if (!(a2.contains(a1.get(x)))) //判断a2中是否存在该元素,没有就将该元素存入a2 a2.add(a1.get(x)); } return a2; //返回a2 } }
运行结果
Set:
元素无序而且不重复;包含HashSet和TreeSet
HashSet:底层数据结构是哈希表;
HashSet是如何保证元素的唯一性?
是通过hashCode和equals来完成。
如果元素的HashCode值相同,就调用equals方法判断内容(此时equals需要复写)
如果元素的HashCode值不同,则元素不同,不会调用equals。
所以一般都会复写HashCode。
注意:对于判断元素是否存在以及删除等操作,均是通过判断元素的hashCode和equals方法。
set集合的功能与Collection一致
TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元是唯一性的依据是:
ompareTo方法 return 0, -1,1
TreeSet排序:
方法一: 让元素自身具备比较性。此方法是需要元素实现Comparable接口。(自然顺序)
方法二: 当元素自身不具备比较性,或具备的比较性不是所需的
这时需要让容器自身具备比较性
定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
以下代码演示TreeSet的两种比较方式
import java.util.*; class PersonTS implements Comparable{ //定义类实现Comparable接口,使其具有比较性 private String name; //定义成员变量 private int age; PersonTS(String name,int age){ //构造函数 this.name=name; this.age=age; } public int compareTo(Object obj){ //覆写compareTo方法,定义排序规则为先按年龄再按姓名排序 if (!(obj instanceof PersonTS)) //判断对比对象是否为Person throw new RuntimeException("不是Person对象"); PersonTS p = (PersonTS)obj; //向下转型为Person sop.sop(this.name+":compareto:"+p.name);//显示具体对比的元素 if (this.age>p.age) //判断年龄大小 return 1; else if(this.age==p.age) //年龄相同时判断姓名 return this.name.compareTo(p.name); else return -1; } public String getName(){ //定义获取姓名方法 return name; } public int getAge(){ //定义获取年龄方法 return age; } } public class CTreeSet{ public static void main(String[] args) { TreeSet ts = new TreeSet(); //定义ts集合并存入元素,用以演示按元素本身的排序规则排序 ts.add(new PersonTS("a1",11)); ts.add(new PersonTS("a2",12)); ts.add(new PersonTS("a3",13)); ts.add(new PersonTS("b2",12)); ts.add(new PersonTS("b2",12)); TreeSet ts2 = new TreeSet(new MyComparePerson()); //定义ts2集合并存入元素,并将比较器作为参数传给集合 ts2.add(new PersonTS("a1",11)); //用以演示按定义的比较器的排序规则排序 ts2.add(new PersonTS("a4",12)); ts2.add(new PersonTS("a1",13)); ts2.add(new PersonTS("b2",12)); ts2.add(new PersonTS("b2",12)); for (Iterator it=ts.iterator();it.hasNext() ; ){ PersonTS p = (PersonTS)it.next(); sop.sop("元素本身排序方式"+p.getName()+":"+p.getAge()); } for (Iterator it=ts2.iterator();it.hasNext() ; ){ PersonTS p = (PersonTS)it.next(); sop.sop("自定义比较器排序方式"+p.getName()+":"+p.getAge()); } } } class MyComparePerson implements Comparator{ //定义类实现Comparator,使其具备比较器的功能 public int compare(Object o1,Object o2){ //覆写compare方法,定义先按照姓名再按照年龄排序 if (!(o1 instanceof PersonTS)&&!(o2 instanceof PersonTS))//判断对比对象是否为Person throw new RuntimeException("不是Person对象"); PersonTS p1= (PersonTS)o1; //将对比元素向下转型为PersonTS PersonTS p2= (PersonTS)o2; int num = p1.getName().compareTo(p2.getName()); //先按照姓名排序 if(num==0){ //判断姓名是否相同,如果相同再对比其年龄 if(p1.getAge() > p2.getAge()) return 1; else if (p1.getAge() == p2.getAge()) return 0; else return -1; } else return num; } }
运行结果
特殊的集合类Map
Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1.添加
put(K key,V value)
putAll(Map<? extends K,? extends V> m )
2.删除
clear()
remove(Object key)
3.判断
containValue(Object value)
containKey(Object key)
isEmpty()
4.获取
get(Object key)
size()
value()
entrySet()
Map
|--HashTable<K,T>:底层是哈希表结构,不可以存入null键null值,该集合是线程同步的。
|--HashMap:底层是哈希表数据结构,无序,允许使用null值和null键,该集合是线程不同步的。
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给集合中的键排序。
和Set很像,其实Set底层就是调用的Map集合。
map集合的两种取出方式:
1.keySet: Set<k> keySet
将map中所有的键存入到Set集合,应为Set具备迭代器,所以可以用迭代方式取出所有的键
再根据get方法,获取每一个键对应的值。
Map集合的取出原理:将map集合转为Set集合,通过Set集合迭代器取出元素
2.entrySet: Set<Map.Entry<k,v>> entrySet
将map集合中的映射关系存储到Set集合中。
演示代码
需求:
学生属性: 姓名,年龄
注意:姓名和年龄相同的视为同一学生
保证学生的唯一性
1.描述学生
2.定义map容器,将学生作为键,地址作为值,存入。
3.获取map集合的元素
import java.util.*; class Student implements Comparable<Student>{ //定义类实现Comparable接口,使其具备比较性 private String name; //定义成员变量 private int age; Student(String name,int age){ //定义带参数构造函数 this.name = name; this.age = age; } public int hashCode(){ //覆写hashCode方法,自定义获取hashcode方式 return name.hashCode()+age*13; } public boolean equals(Object obj){ //自定义比较类型 if(!(obj instanceof Student)) //判断对比对象是否是Student throw new ClassCastException("类型不匹配"); Student s = (Student)obj; //将对比对象向下转型为Student sop.sop(this.name+":equals:"+s.name); return this.name.equals(s.name) && this.age==(s.age);//定义相同条件为姓名年龄均相同 } public int compareTo(Student s){ //默认排序方式为按照年龄排序 int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num == 0) return this.name.compareTo(s.name); else return num; } public String getName(){ //定义获取姓名方法 return name; } public int getAge(){ //定义获取年龄方法 return age; } } public class DmapDemo{ public static void main(String[] args){ HashMap<Student,String> hm = new HashMap<Student,String>(); hm.put(new Student("mike1",12),"shanghai"); hm.put(new Student("lili1",12),"shanghai"); hm.put(new Student("mike2",12),"chengdu"); hm.put(new Student("lili2",11),"chengdu"); hm.put(new Student("mike3",12),"beijing"); hm.put(new Student("lili3",13),"beijing"); TreeMap<Student,String> tm = new TreeMap<Student,String>(/*new MyCompare()*/); tm.put(new Student("mike1",12),"shanghai"); tm.put(new Student("lili1",12),"shanghai"); tm.put(new Student("mike2",11),"chengdu"); tm.put(new Student("lili2",11),"chengdu"); tm.put(new Student("mike3",12),"beijing"); tm.put(new Student("lili3",13),"beijing"); Set<Student> keySet = hm.keySet(); Set<Map.Entry<Student,String>> entrySet = tm.entrySet(); sop.sop("HashMap的键值对为无序排列:"); for (Iterator <Student>it = keySet.iterator(); it.hasNext();){ Student key = it.next(); sop.sop(key.getName()+":"+key.getAge()+"....."+hm.get(key)); } sop.sop("TreeMap的键值对按照自定规则排序:"); for (Iterator <Map.Entry<Student,String>> it = entrySet.iterator(); it.hasNext();){ Map.Entry key = it.next(); Student s = (Student)key.getKey(); sop.sop(s.getName()+":"+s.getAge()+"....."+key.getValue()); } } } class MyCompareStu implements Comparator<Student>{//定义按照学生姓名排序的比较器。 public int compare(Student s1,Student s2){ int num = s1.getName().compareTo(s2.getName()); if(num==0) return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); else return num; } }
运行结果