集合Collection
1.集合存在的理由
数据多了用对象存,对象多了用集合存!
它是变长的,可以接受各种不同的对象,是数组不能替代的!
2.大致结构
3.各子类数据结构:所以有什么特性自然明了
ArrayList:数组
LinkedList:双向非循环链表
HashSet:hash表
4.父接口Collection都干了什么事
存在有包java.util中
5.List子接口都干了什么事
6.ArraylList
1 package collection; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.ListIterator; 6 7 8 9 /** 10 * ArrayList的使用,注意iterator和listIterator 11 */ 12 public class ArrayListDemo { 13 14 public static void main(String[] args) { 15 // TODO Auto-generated method stub 16 // 构造初始容量为15的空列表 17 ArrayList al=new ArrayList(15); 18 19 // 添加 20 al.add("hi_one"); 21 al.add("hi_two"); 22 al.add(1,"hi_three"); 23 al.add("hi_one"); 24 25 // 删除 26 ArrayList bl=new ArrayList(al); 27 // bl.removeRange(1,2);//不可用!!protected,继承了的子类可以使用该方法 28 sop("start "+"bl="+bl+"\n"); 29 bl.remove(1); 30 bl.remove("hi_one"); 31 32 // 修改 33 bl.set(0, "hi"); 34 35 // 查找 36 String s=(String) al.get(1); 37 int index=al.lastIndexOf("hi_one"); 38 sop("later "+"bl="+bl+"\n"); 39 40 sop("\n"+"start:"+"al"+"\n"); 41 // 迭代器 itrator()返回一个内部类对象,该对象封装了迭代操作方法hasNext(),next(),remove() 42 for(Iterator it=al.iterator();it.hasNext();){ 43 // 在使用迭代操作集合时,就不要用集合本身的方法操作数据,否则可能 44 // java.util.ConcurrentModificationException异常 45 // 所以,即使能够获取到元素,也没有add(),set()方法!!! 46 sop(it.next()); 47 } 48 // List子类特有迭代器listIterator(),增加方法: 49 // add();hasPrevious();previous();previousIndex();nextIndex();set() 50 ListIterator lt=al.listIterator(); 51 sop("\n"+"later:"+"al逆向遍历,并将元素后面添加!"+"\n"); 52 53 //逆向遍历,并将元素后面添加! 54 while(lt.hasNext()){ 55 Object obj=lt.next();//常用方式 56 lt.set(obj+"!"); 57 } 58 while(lt.hasPrevious()){ 59 sop(lt.previous()); 60 } 61 62 63 } 64 public static void sop(Object obj){ 65 System.out.println(obj); 66 } 67 68 }
练习:删除集合中相同的对象,“相同”的标准自定义
1 import java.util.ArrayList; 2 import java.util.Iterator; 3 /** 4 * 5 *去除重复对象:以id和Name同则视为同 6 */ 7 public class ArrayListTest2 { 8 9 public static void main(String[] args) { 10 // 定义容器 11 ArrayList al=new ArrayList(); 12 // 初始化 13 al.add(new Student(1,"h1")); 14 al.add(new Student(2,"h2")); 15 al.add(new Student(1,"h1")); 16 al.add(new Student(3,"h2")); 17 // 打印原始//可用迭代器 18 System.out.println("start: "); 19 for(int i=0;i<al.size();i++){ 20 Student s=(Student) al.get(i); 21 System.out.print(s.getId()+" "+s.getName()+";"); 22 } 23 // 删除重复 24 al=ArrayListTest2.noRepeat(al); 25 System.out.println("\n"+"later: "); 26 for(int i=0;i<al.size();i++){ 27 Student s=(Student) al.get(i); 28 System.out.print(s.getId()+" "+s.getName()+";"); 29 } 30 } 31 public static ArrayList noRepeat(ArrayList al){ 32 // 定义容器 33 ArrayList bl=new ArrayList(); 34 Iterator it=al.iterator(); 35 while(it.hasNext()){ 36 Student obj=(Student)it.next(); 37 // 当调用contains,remov等方法时,默认会调用equals 38 if(!bl.contains(obj)) bl.add(obj); 39 40 } 41 return bl; 42 } 43 44 } 45 //定义对象 46 class Student{ 47 private int Id; 48 private String Name; 49 Student(int id,String name){ 50 this.Id=id; 51 this.Name=name; 52 } 53 public int getId(){ 54 return Id; 55 } 56 public String getName(){ 57 return Name; 58 } 59 // 重写equals,否则将以默认的equals判读对象是否相同!!! 60 public boolean equals(Object obj){ 61 if(!(obj instanceof Student)) return false; 62 Student s=(Student)obj; 63 return this.Id==s.Id && this.Name.equals(s.Name); 64 } 65 }
7.LinkedList
增加:除了父类的add,addAll
头插:void addFirst(E e) boolean offerFirst(E e)
尾插:void addLast(E e) boolean offerLast(E e)
删除:
获取并移除头:E pollFirst(),空则返回null,removeFirst()类似,但空抛出异常NoSuchElementException
获取并移除尾:E pollLast(),空则返回null
修改:
查询:
获取不移除头:E peekFirst(),空则返回null,getFirst()类似,但空抛出异常NoSuchElementException
获取不移除尾:E peekLast(),空则返回null
堆栈:
弹出: E pop()
移除并返回此列表的第一个元素 抛出:NoSuchElementException
- 如果此列表为空
压栈:public void push(E e) 等效于 addFirst(E)
。
练习:LinkedList模拟队列数据结构
1 import java.util.LinkedList; 2 3 class DuiLie{ 4 private LinkedList link; 5 DuiLie(){ 6 link=new LinkedList(); 7 } 8 //头出并删除 9 public final Object pop(){ 10 return link.pollFirst(); 11 } 12 //尾入 13 public final void push(Object e){ 14 link.addLast(e); 15 } 16 //判空 17 public boolean isEmpty(){ 18 return link.isEmpty(); 19 } 20 } 21 public class LinkListedDemo { 22 23 public static void main(String[] args) { 24 DuiLie d=new DuiLie(); 25 //入队 26 d.push("a"); 27 d.push("b"); 28 d.push("c"); 29 //出队 30 System.out.println(d.pop()); 31 System.out.println(d.pop()); 32 System.out.println(d.pop()); 33 } 34 35 }
8.Set接口都干了什么事
9.HashSet
特点:无序、不重复
不重复标准:当且仅当 两对象的hashCode()值相同且equals()返回true 时,认为两对象相同
也就是说:HashSet集合的添加、删除、contains等操作都依赖hashCode()和equals()两个方法!!
实例:在HashSet中存入和取出对象,并遵循自定义的“相同”规则
方式一:让存入的对象本身具有比较性:让类实现Comparable接口复写其compareTo方法
1 import java.util.Iterator; 2 import java.util.TreeSet; 3 4 /** 5 * 6 *定义TreeSet集合,存入自定义对象,自定义比较规则 7 *规则:首要按年龄排,在按姓名.compareTo()按字典排,两者相同则认为相同 8 */ 9 public class TreeSetDemo { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 TreeSet ts=new TreeSet(); 14 // 存入 15 ts.add(new Teacher("abc",20)); 16 ts.add(new Teacher("Abc",20)); 17 ts.add(new Teacher("adf",21)); 18 ts.add(new Teacher("jdc",23)); 19 // ts.add(new People(1,"2")); 20 Iterator it=ts.iterator(); 21 // 需要解决,加入不同类的对象,准备让所有的类都实现Comparable接口?? 22 // ts.add(new Teacher("abc",20)); 23 // 输出 24 while(it.hasNext()){ 25 Teacher t=(Teacher)it.next(); 26 System.out.println(t.getName()+t.getAge()); 27 28 } 29 } 30 31 } 32 // 实现Comparable接口=》具有比较性 33 class Teacher implements Comparable{ 34 private String Name; 35 private int Age; 36 public String getName() { 37 return Name; 38 } 39 public int getAge() { 40 return Age; 41 } 42 Teacher(String name , int age){ 43 this.Name=name; 44 this.Age=age; 45 } 46 @Override 47 public int compareTo(Object o) { 48 // TODO Auto-generated method stub 49 if(!(o instanceof Teacher)) return -1; 50 if(this.Age>((Teacher)o).getAge()) return 1; 51 if(this.Age==((Teacher)o).getAge()){ 52 //年龄相同时按字符串的字典顺序排,如字符相同,返回0剔除 53 return this.Name.compareTo(((Teacher)o).getName()); 54 } 55 else return -1; 56 } 57 58 }
1 import java.util.HashSet; 2 import java.util.Iterator; 3 4 /** 5 * 6 *往hashSet集合存入自定义对象,可重复 7 *hashSet如何比较:与List的不一样,要先调用hashCode(),当值相同时继续调用equals(),当且仅当hash值相同且equals为true才相同 8 *先调用比较对象的hashCode值是否相同,显然如果不重写hashCode方法,new出来的对象hash值都不同 9 *当hash值不同时,认为是不同的对象;当hash值相同时,这是才会调用equals方法!!!重写equals方法,自定义判断相同条件 10 */ 11 public class HashSetDemo { 12 13 public static void main(String[] args) { 14 // 定义集合 15 HashSet hs=new HashSet(); 16 hs.add(new People(1,"hash1")); 17 hs.add(new People(2,"hash2")); 18 hs.add(new People(1,"hash1")); 19 hs.add(new People(3,"hash3")); 20 hs.add(new People(3,"hash3")); 21 hs.add(new People(3,"hash3")); 22 // 获取 23 Iterator it=hs.iterator(); 24 while(it.hasNext()){ 25 People p=(People)(it.next()); 26 System.out.print(p.getId()+" "+p.getName()+";"); 27 } 28 System.out.println(""); 29 } 30 31 } 32 // 常用写法:复写hashCode与equals方法,判断对象是否相等 33 class People{ 34 private int Id; 35 private String Name; 36 People(int id ,String name){ 37 this.Id=id; 38 this.Name=name; 39 } 40 public int getId(){ 41 return Id; 42 } 43 public String getName(){ 44 return Name; 45 } 46 public boolean equals(Object obj){ 47 // System.out.println(this.Id+this.Name+"...equals..."+((People)obj).Id+((People)obj).Name);//测试调用equals 48 if(!(obj instanceof People)) return false; 49 return this.Id==((People)obj).Id && this.Name.equals(((People)obj).Name); 50 } 51 public int hashCode(){ 52 // 相同对象的hash值相同,注意用到了包装类,因为int型的Id本身不是对象,不能调用Object的方法 53 return new Integer(this.Id).hashCode()+this.Name.hashCode(); 54 } 55 }
10.SortedSet接口
11.TreeSet
特点:无序(不按存入顺序) 有序(会按值排序)
实例:存入自定义对象--看12
12. 泛型的使用
泛型——广泛的类型,可以通过泛型限定我们使用的 类、方法、接口,从而得到规范,排除了某些安全隐患——如传入非指定的参数,将会编译出错,错误从运行时转至编译时。
泛型的语法:
1 class Point<T> { 2 //这里用T来表示不确定的类型 3 private T x; 4 ...泛型类中可以使用其他的泛型方法——灵活 5 }
1 public <E> void show(E e) { 2 System.out.println(e.getClass()); 3 }
1 //定义一个泛型接口 2 interface Inter<T> 3 { 4 public void print(T t); 5 } 6 7 //实现方式一:类实现接口的时候就指定类型 8 class InterDemo1 implements Inter<String> { 9 public void print(String t) { 10 System.out.println("print: " + t); 11 } 12 } 13 14 //实现方式二:类实例化的时候才指定类型 15 class InterDemo2<T> implements Inter<T> { 16 public void print(T t) { 17 System.out.println("print: " + t); 18 } 19 }
泛型的应用——在TreeSet于LinkedList集合中存入锥体(名字,高,底),按照体积排序,底面可以是矩形圆等,名字和体积相同则认为是同一对象,用同一方法遍历
1 /** 2 * 类中使用泛型 3 * 方法中使用泛型 4 * 接口中使用泛型 5 */ 6 package collection; 7 8 import java.util.Collection; 9 import java.util.Comparator; 10 import java.util.Iterator; 11 import java.util.LinkedList; 12 import java.util.TreeSet; 13 14 /** 15 * 需求:在集合中存入锥,按照锥的体积排序,集合传入泛型接口的比较器,体积相同且名字相同,认为是同一个锥 16 * 尝试用不同的集合存入锥,用同一个方法打印不同集合中锥对象 17 */ 18 19 public class GenericsDemo { 20 21 public static void main(String[] args) { 22 // TreeSet添加 23 TreeSet<Zhui> tr = new TreeSet<Zhui>(new MyComp()); 24 25 tr.add(new Zhui("Zhui1", 5.0, new Juxing(1.5, 2.5))); 26 tr.add(new Zhui("Yuan1", 3.0, new Yuan(2.5))); 27 tr.add(new Zhui("Zhui3", 5.0, new Juxing(1.5, 2.5))); 28 tr.add(new Zhui("Zhui2", 6, new Juxing(1, 2))); 29 tr.add(new ChildZhui("Zhui2", 6, new Juxing(1, 2))); 30 31 // LinkedList添加 32 LinkedList<Zhui> li = new LinkedList<Zhui>(); 33 34 li.add(new Zhui("Zhui1", 5.0, new Juxing(1.5, 2.5))); 35 li.add(new Zhui("Yuan1", 3.0, new Yuan(2.5))); 36 li.add(new Zhui("Zhui3", 5.0, new Juxing(1.5, 2.5))); 37 li.add(new Zhui("Zhui2", 6, new Juxing(1, 2))); 38 li.add(new ChildZhui("Zhui2", 6, new Juxing(1, 2))); 39 40 // 打印TreeSet集合,体会泛型 41 System.out.println("TreeSet"); 42 GenericsDemo.printColl(tr); 43 44 // 打印LinkedList集合,体会泛型 45 System.out.println("LinkedList"); 46 GenericsDemo.printColl(li); 47 } 48 49 // 泛型接口:指定,参数或返回值接收T类型 50 public static <T> void display(T t) { 51 System.out.println(t.getClass()); 52 } 53 54 // 静态泛型方法,可以打印某集合中的锥对象 55 public static <T> void printColl(Collection<T> t) { 56 Iterator<Zhui> it = (Iterator<Zhui>) t.iterator(); 57 while (it.hasNext()) { 58 Zhui z = (Zhui) it.next(); 59 System.out.println(z.getName() + " " + "V:" + z.getArea()); 60 } 61 } 62 } 63 64 // 泛型接口:定义比较器,传至TreeSet构造方法 65 class MyComp implements Comparator<Zhui> { 66 67 @Override 68 // public int compare(Object o1, Object o2) //默认本应该传入Object的 69 public int compare(Zhui o1, Zhui o2) { 70 // TODO Auto-generated method stub 71 int temp = (int) (o1.getArea() - o2.getArea()); 72 73 return temp == 0 ? o1.getName().compareTo(o2.getName()) : temp; 74 } 75 76 } 77 78 /** 79 * 锥,1/3 底面积*高 80 * 81 * @param <B> 82 * 泛型锥底形状 83 * @param height 84 * 高 85 * @param bottom 86 * 底 87 */ 88 // 泛型类——上限 89 class Zhui<B extends Bottom> { 90 private String Name; 91 92 public String getName() { 93 return Name; 94 } 95 96 private B bottom; 97 double height; 98 99 // 脑壳发热的想返回值也搞个泛型,那就不行了,泛型是针对引用型数据的 100 double getArea() { 101 return height * bottom.getArea() / 3; 102 } 103 104 // 构造 105 Zhui(String name, double height, B bottom) { 106 Name = name; 107 this.bottom = bottom; 108 this.height = height; 109 } 110 } 111 class ChildZhui extends Zhui{ 112 113 ChildZhui(String name, double height, Bottom bottom) { 114 super(name, height, bottom); 115 } 116 117 } 118 /** 119 * 抽象底部,有获取面积的抽象方法 120 */ 121 abstract class Bottom { 122 abstract double getArea(); 123 } 124 125 /** 126 * 定义矩形 127 * 128 * @param l 129 * 长 130 * @param h 131 * 宽 132 */ 133 class Juxing extends Bottom { 134 private double l; 135 private double h; 136 137 public Juxing(double l, double h) { 138 this.l = l; 139 this.h = h; 140 } 141 142 @Override 143 double getArea() { 144 // TODO Auto-generated method stub 145 return l * h; 146 } 147 148 } 149 150 /** 151 * 定义圆,继承底部Bottom 152 */ 153 class Yuan extends Bottom { 154 private double r; 155 156 public Yuan(double r) { 157 this.r = r; 158 } 159 160 @Override 161 double getArea() { 162 // TODO Auto-generated method stub 163 return Math.PI * r * r; 164 } 165 166 }
13.需要比较相同总结