/* 集合类(集合框架):存储对象的一种方式 java.util.Collection 为什么出现集合类 面向对象的语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作 就对对象进行存储,集合就是存储对象最常用的一种方式 数组和集合类同是容器,有何不同 数组虽然也可以存储对象,但长度是固定的;而集合长度是可变的 数组中可以存储基本数据类型,集合只能存储对象 集合类的特点 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象 */ import java.util.*; class CollectionMainDemo1 { public static void main(String[] args) { method_retain(); base_method(); method_get(); } public static void base_method() { //创建一个集合容器,使用Collection接口的子类,ArrayList ArrayList al = new ArrayList(); //1.添加元素 /* add方法的参数类型是Object以便接收任意类型的对象 集合中存储的都是对象的引用(地址) */ al.add("java01"); //add(Object obj) al.add("java02"); al.add("java03"); al.add("java04"); sop(al); //获取个数,集合长度 sop("size:"+al.size()); //删除元素 al.remove("java02"); //al.clear(); //清空集合 sop(al); //判断元素 sop("java03是否存在"+al.contains("java03")); sop("集合是否为空"+al.isEmpty()); } public static void method_retain() { ArrayList al1 = new ArrayList(); al1.add("java01"); al1.add("java02"); al1.add("java03"); al1.add("java04"); ArrayList al2 = new ArrayList(); al2.add("java01"); al2.add("java02"); al2.add("java05"); al2.add("java06"); al1.retainAll(al2); //取交集,al1中只会保留和al2相同的元素 al1.removeAll(al2); //移除al1中和al2相同的元素 sop("al1:"+al1); sop("al2:"+al2); } /* 迭代器 其实就是集合取出元素的方式 */ public static void method_get() { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java03"); al.add("java04"); Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素 sop(it.next()); sop(it.hasNext()); //有元素时返回真 while(it.hasNext) { sop(it.next()); } } public static void sop(Object obj) { System.out.println(obj); } } /* List集合共性方法 Collection |--List:元素是有序的,元素可以重复,因为该集合体系有索引 |--ArrayList:底层是数组数据结构,特点:查询速度很快,增删改速度慢,元素越多越明显 |--LinkedList:底层是链表数据结构,特点:查询速度慢,增删改速度快 |--Vector:底层是数组数据结构,Vector是同步的,ArrayList是不同步的 |--Set:元素是无序的,元素不可以重复,因为该体系没有索引 |--HashSet:底层数据结构是hash表 HashSet是如何保证元素的唯一性的呢? 是通过元素的HashCode值相同,才会判断equals是否为true 如果元素的hashCode值不同,则不会调用equals |--TreeSet:可以对Set集合中的元素进行排序 List: 特有方法:凡是可以操作角标的方法都是该体系特有的方法 增 add(index,element); addAll(index,Collection); 删 remove(index); 改 set(index,element); 查 get(index); subList(from,to); listIterator(); */ import java.util.*; class ListMainDemo1 { public static void main(String[] args) { method_base(); listIteratorDemo(); } public static void method_base() { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java03"); al.add("java04"); //在指定位置添加元素 sop("原集合是:"+al); al.add(1,"java09"); //在角标1的位置插入元素 sop("在角标1的位置插入元素后的结果是:"+al); //删除指定位置的元素 al.remove(2); sop("删除角标为2的元素后的结果是:"+al); //修改元素 al.set(1,"java10"); sop("将角标为1的元素修改为java10后的结果:"+al); //通过角标获取元素 sop("通过角标获取元素:"+al); sop("获取到的元素:get(2):"+al.get(2)); //获取所有元素 sop("利用for循环获取所有元素:"); for(int x =0; x<al.size(); x++) { sop("al("+x+")="+al.get(x)); } sop("利用Iterator获取所有元素:"); for(Iterator it = al.iterator(); it.hasNext(); ) { sop("next:"+it.next()); } //通过indexOf获取对象的位置 sop("通过indexOf获取java03所在的位置:"+al.indexOf("java03")); //取一个子列表 List sub = al.subList(1,3);//从原集合中取出1到3的元素,包含1,不包含3 sop("sub="+sub); } /* 列表迭代器 ListIterator是Iterator的子接口 在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。 所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator的方法是有限的,只能对元素进行判断,取出,删除 的操作,如果想要其他的操作,如添加,修改等,就需要使用其子接口,ListIterator。 该接口只能通过List集合的ListIterator方法获取 */ public static void listIteratorDemo() { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java03"); al.add("java04"); sop("原集合是"+al); /*在迭代过程中,准备添加或者删除元素 这种是有问题的方法 for(Iterator it = al.iterator(); it.hasNext(); ) { Object obj = it.next(); if(obj.equals("java02")) //al.add("java05"); //这里会抛出异常,因为连个容器在同时操作一个数据 it.remove();//将java02的引用从集合中删除 } */ for(ListIterator li = al.listIterator(); li.hasNext(); x++) { sop("hasNext():"+li.hasNext()); sop("hasPrevious():"+li.hasPrevious()); Object obj = li.next(); if(obj.equals("java02")) { //li.add("java05"); //在java02后面添加java05 li.set("java06"); //把java02修改成java06 } } sop("迭代以后的集合"+al); } public static void sop(Object obj) { System.out.println(obj); } } /* Vector特殊的地方:枚举 枚举,就是Vector的特有取出方式 发现枚举和迭代器很象 此接口的功能与 Iterator 接口的功能是重复的。 此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。 新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。 */ class VectorMainDemo1 { public static void main(String[] args) { Vector v = new Vector(); v.add("java01"); v.add("java02"); v.add("java03"); v.add("java04"); Enumeration ne = v.elments(); while(en.hasMoreElements()) { System.out.println(en.netElement()); } } } /* LinkedList模拟一个堆栈或者队列数据结构 堆栈:先进后出 First in Last out(FILO) 如同一个杯子 队列:先进先出 First in First out(FIFO) 如同一个水管 */ import java.util.*; class QueueMainDemo1 { private LinkedList link; QueueMainDemo1() { link = new LinkedList(); } //添加方法 public void myAdd(Object obj) { link.addFirst(obj); //将指定元素插入到此列表的开头 } //获取方法 public Object myGet() { return link.removeLast(); //返回此列表最后一个元素 } //清空方法 public boolean isNull() { return link.isEmpty(); } public static void main(String[] args) { } } class LinkedListMainDemo1 { public static void main(String[] args) { QueueMainDemo1 q = new QueueMainDemo1(); q.myAdd("java01"); q.myAdd("java02"); q.myAdd("java03"); q.myAdd("java04"); System.out.println(q.myGet()); } } /* 练习:去除ArrayList中重复的元素 */ import java.util.*; class ArrayListTest1 { public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java01"); al.add("java02"); al.add("java02"); al.add("java03"); al.add("java03"); System.out.println(al); al = singleElement(al); System.out.println(al); } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器 ArrayList newAl = new ArrayList(); for(Iterator it = al.iterator(); it.hasNext(); ) { Object obj = it.next(); if(!newAl.contains(obj))//如果临时容器中,不包含原容器中的元素 newAl.add(obj); //就存入临时容器中 } return newAl; } } /* ArrayList练习2 将自定义对象作为元素,存储到ArrayList集合中,并去除重复元素 比如:存人对象,同姓名同年龄,视为同一个人,为重复元素 List集合判断元素是否相同,依据的是元素的equals方法 */ import java.util.*; class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public boolean equals(Object obj) //重写父类的equals方法,因为Object的equals方法比较的是地址 //为什么重写equals,因为contains底层用的就是equals { if(!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name) && this.age == p.age; } } class ArrayListTest2 { public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new Person("lisi01",30)); al.add(new Person("lisi02",23)); al.add(new Person("lisi03",32)); al.add(new Person("lisi03",32)); al.add(new Person("lisi04",20)); al.add(new Person("lisi04",20)); Iterator it = al.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); System.out.println(p.getName()+"::"+p.getAge()); } ArrayList al1 = singleElement(al); System.out.println(); Iterator it1 = al1.iterator(); while(it1.hasNext()) { Person p = (Person)it1.next(); System.out.println(p.getName()+"::"+p.getAge()); } } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器 ArrayList newAl = new ArrayList(); for(Iterator it = al.iterator(); it.hasNext(); ) { Object obj = it.next(); if(!newAl.contains(obj))//如果临时容器中,不包含原容器中的元素 newAl.add(obj); //就存入临时容器中 } return newAl; } } /* Set: 无序,不可以重复元素. |--HashSet: 数据结构是哈希表.线程是非同步的. 保证元素唯一性的原理:判断元素的hashCode值是否相同. 如果相同,还会继续判断元素的equals方法 |--TreeSet: 可以对Set集合中的元素进行排序. 底层数据结构是二叉树. 保证元素的唯一性的依据是compareTo方法return 0. TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现compareable接口 覆盖compareTo方法,这种方式也称为元素的自然顺序,或者叫做默认顺序 TreeSet排序的第二种方式:当元素自身不具备比较性或比较性不是所需要的时候 就需要让集合自身具备比较性,在集合初始化时就有了比较方式,所以我们需要 参阅集合的构造函数 */ class HashSetMainDemo1 { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); hs.add("java01"); hs.add("java02"); hs.add("java03"); hs.add("java04"); Iterator it = hs.iterator(); while(it.hasNext()) { sop(it.next()); } } } /* HashSet添加自定义对象 */ import java.util.*; /* 在实际开发中,只要描述这个事物要往集合里面存 一般都会重写hashCode() 和 equals()方法 */ class Person { private String name; private int age; public static void main(String[] args) { } Person(String name,int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } /* 重写hashCode,因为hashSet给每个对象赋了不同的hash值,所以equals没有运行 所以这里重写hash值,让每个对象hash值相同,这时候equals就运行了 */ public int hashCode() { System.out.println(this.name+"....hashCode"); return name.hashCode()+age*37; //乘整数是为了保证hash值得唯一性 } /* 重写equals因为默认的equals是判断地址 */ public boolean equals(Object obj) { if(!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"...equals.."+p.name); return this.name.equals(p.name) && this.age == p.age; } } class HashSetMainDemo2 { 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("a3",13)); hs.add(new Person("a4",14)); hs.add(new Person("a4",14)); //对于判断元素是否存在以及删除等操作,都依赖于元素的hashCode()和equals() System.out.println(hs.contains(new Person("a1",11))); // hs.remove(new Person("a2",12)); Iterator it = hs.iterator(); while(it.hasNext()) { Person p = (Person)it.next(); System.out.println(p.getName()+"::"+p.getAge()); } } } /* TreeSet:可以对Set集合中的元素进行排序 默认按照Ascii码表排序 */ class TreeSetMainDemo1 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add("cbcd"); ts.add("bsdf"); ts.add("aaaa"); ts.add("ebd"); Iterator it = ts.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } /* 存储自定义对象 需求往TreeSet集合中存储自定义对象学生 想按照学生的年龄进行排序 */ import java.util.*; class 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; } } class TreeSetMainDemo2 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22)); ts.add(new Student("lisi007",20)); //2个以上对象会报错 ts.add(new Student("lisi09",19)); ts.add(new Student("lisi01",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } /* 以上结果会报错,因为TreeSet在排序的时候,我们的对象 根本不具备比较性,说白了就是,TreeSet根本不知道你排 序的依据是什么,那么它怎么知道该如何给你排序呢?所以 会报错,那么因此,如果我们想进行排序该怎么办呢? 答: 想要进行排序那么我们必须具备比较性,那么我们又如何 才能具备比较性呢? TreeSet给我们提供了一个接口Comparable,你只要实现这个 接口,那么就具备了比较性,TreeSet就可以帮你进行排序了 */ import java.util.*; class Student implements Comparable //该接口强制让学生具备比较性 { private String name; private int age; public int compareTo(Object obj) { if(!(obj instanceof Student)) throw new RuntimeException("不是学生对象"); Student s = (Student)obj; System.out.println(this.name+"...compareto..."+s.name); //比较过程 if(this.age>s.age) return 1; //如果大于返回整数 if(this.age==s.age) //如果等于返回0;0表示两个对象相等 { return this.name.compareTo(s.name); //如果主要比较因素相等,就比较次要因素 //它返回的也是0、1、或负数 } return -1; //小于返回负数 } Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } class TreeSetMainDemo3 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22)); ts.add(new Student("lisi007",20)); ts.add(new Student("lisi09",19)); ts.add(new Student("lisi01",40)); ts.add(new Student("lisi03",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } /* 二叉树:可以减少比较次数,提高性能 二叉树在元素越多的时候,它会自动取折中值 二叉树默认按照从小到大取数据 */ //需求,数据怎么存进去的怎么取出来 import java.util.*; class Student implements Comparable //该接口强制让学生具备比较性 { private String name; private int age; public int compareTo(Object obj) //TreeSet集合在比较的时候和compareTo没关系,它只看compareTo的返回值 { return 1; //代表待比较的数比源数据大,因为二叉树默认按照从小到大取数据,所以怎么存进去的怎么取 //如果想倒序取数据,直接返回-1即可 } Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } class TreeSetMainDemo4 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22)); ts.add(new Student("lisi007",20)); ts.add(new Student("lisi09",19)); ts.add(new Student("lisi01",40)); ts.add(new Student("lisi03",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } /* TreeSet第二种排序方式:实现Comparator 当元素自身不具备比较性或比较性不是所需要的时候 这时需要让容器自身具备比较性 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数 当两种排序都存在时以比较器为主 */ import java.util.*; class Student implements Comparable //该接口强制让学生具备比较性 { private String name; private int age; public int compareTo(Object obj) { if(!(obj instanceof Student)) throw new RuntimeException("不是学生对象"); Student s = (Student)obj; System.out.println(this.name+"...compareto..."+s.name); //比较过程 if(this.age>s.age) return 1; //如果大于返回整数 if(this.age==s.age) //如果等于返回0;0表示两个对象相等 { return this.name.compareTo(s.name); //如果主要比较因素相等,就比较次要因素 //它返回的也是0、1、或负数 } return -1; //小于返回负数 return 1; } Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } class TreeSetMainDemo4 { public static void main(String[] args) { TreeSet ts = new TreeSet(new MyCompare()); //定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数 ts.add(new Student("lisi02",22)); ts.add(new Student("lisi007",20)); ts.add(new Student("lisi09",19)); ts.add(new Student("lisi01",40)); ts.add(new Student("lisi03",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } class MyCompare implements Comparator //比较器 { public int compare(Object o1,Object o2) { Student s1 = (Student)o1; Student s2 = (Student)o2; return s1.getName().compareTo(s2.getName()); //以姓名进行排序 } } /* 练习:按照字符串长度排序 字符串本身具备比较性,但是它的比较方式不是所需要的 这时候就只能使用比较器 */ import java.util.*; class TreeSetTest1 { public static void main(String[] args) { TreeSet ts = new TreeSet(new StringLengthComparator()); al.add("ts01"); al.add("ts022"); al.add("ts0312"); Iterator it = ts.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } class StringLengthComparator implements Comparator { public int compare(Object o1,Object o2) { String s1 = (String)o1; String s2 = (String)o2; /* if(s1.length()>s2.length()); return 1; if(s1.length()==s2.length()) return 0; return -1; */ int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if(num==0) return s1.compareTo(s2); //主要条件要是比较不出来就比较次要元素 return num; } } /* 当我们向集合中存放不同类型的数据时运行时可能会出错 泛型集合:JDK1.5版本以后出现的新特性。用于解决安全问题,是一种安全机制 好处 1.将运行时期出现的ClassCastException错误,转移到了编译时期,方便于程序员解决问题 让运行时期问题减少,安全 2.避免了强制转换的麻烦. 泛型格式:通过<>来定义要操作的引用数据类型 在使用java提供的对象时,什么时候写泛型呢? 答: 通常在集合框架中很常见,只要见到<>就要定义泛型,其实<>就是用来接收类型的 当使用集合时,将集合中要存储的数据类型作为参数传递到<>即可,如同函数传参数一样 */ import java.util.*; class GenericDemo1 { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); //定义一个ArrayList容器,该容器是String类型 al.add("abc01"); al.add("abc02"); al.add("abc03"); Iterator<String> it = al.iterator(); while(it.hasNext()) { String s = it.next(); System.out.println(s+":"+s.length()); } } } //泛型在比较器中的应用 import java.util.*; class GenericDemo2 { public static void main(String[] args) { TreeSet<String> ts = new TreeSet<String>(new LenComparator()); al.add("ts01"); al.add("ts022"); al.add("ts0312"); Iterator<String> it = ts.iterator(); while(it.hasNext()) { String s = it.next(); System.out.println(s); } } } class LenComparator implements Comparator<String> //比较器也可以加泛型,避免强转 { public int compare(String o1,String o2) { int num = new Integer(o1.length()).compareTo(new Integer(o2.length());//按长度比较 if(num==0) return o1.compareTo(o2); return num; } } /* 泛型类 什么时候定义泛型类? 当类中要操作的引用数据类型不确定的时候 早期定义Object来完成扩展 现在定义泛型来完成扩展 */ class Worker { } class Student { } //泛型前 /* class Tool { private Object obj; public void setObject(Object obj) { this.obj = obj; } public Object getObject() { return obj; } } */ //泛型后 class Utils<Generics> { private Generics g; public void setObject(Generics g) { this.g = g; } public Generics getObject() { return g; } } class GenericDemo3 { public static void main(String[] args) { Utils<Worker> u = new Utils<Worker>(); u.setObject(new Worker()); Worker w = u.getObject(); //避免了强转,直接让错误转移到了编译时期 /* Tool t = new Tool(); t.setObject(new Student()); Worker w = (Worker)t.getObject(); //在出现泛型之前需要进行强转 */ } } /* 泛型方法 */ class Demo<T> { public void show(T t) { System.out.println("Show: " + t); } public void print(T t) { System.out.println("Print: " + t); } } class GenericDemo4 { public static void mian(String[] args) { Demo<Integer> d = new Demo<Integer>(); d.show(new Integer(4)); d.print("haha"); //这样就会报错,因为new对象时已经指明类型为Integer } } /* 以上就是泛型类的一个局限性 泛型类定义的泛型,在整个类中有效。如果被方法使用 那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了 为了让不同方法可以操作不同的类型,而且类型还不确定 那么可以将泛型定义在方法上 */ class Demo { public<T> void show(T t) { System.out.println("Show: " + t); } public<T> void print(T t) { System.out.println("Print: " + t); } } class GenericDemo5 { public static void main(String[] args) { Demo d = new Demo(); d.show("haha"); d.show(new Integer(4)); } } /* 静态泛型方法 静态方法不可以访问类上定义的泛型,如果静态方法操作的的应用数据类型不确定,可以将泛型定义在方法上 */ class Demo<T> { public void show(T t) { System.out.println("Show: " + t); } public<Q> void print(Q q) { System.out.println("Print: " + t); } public static<W> void method(W w) //静态泛型方法 { } } class GenericDemo5 { public static void main(String[] args) { Demo<String> d = new Demo<String>(); d.show("haha"); d.print(5); d.print("hehe"); Demo.method("hahaha"); } } /* 泛型接口 */ interface Inter<T> { void show(T t); } /* class Interimpl implements Inter<String> { public void show(String t) { System.out.println("Show: " + t); } } */ class InterImpl<T> implements Inter<T> { public void show(T t) { System.out.println("Show: " + t); } } class GenericDemo6 { public static void main(String[] args) { InterImpl<Integer> i = new InterImpl<Integer>(); i.show(4); /* InterImpl i = new InterImpl(); i.show("haha"); */ } } /* 泛型限定 ?通配符。也可以理解为占位符 泛型的限定: 限定?可接受的类型范围 ? extends E: 可以接收E类型或者E的子类型 上限定(上限) ? super E: 可以接收E类型或者E的父类型 下限定(下限) */ //上限应用 import java.util.*; class GenericDemo7 { /* public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc01"); al.add("abc02"); al.add("abc03"); ArrayList<Integer> al1 = new ArrayList<Integer>(); al1.add(4); al1.add(8); al1.add(1); printColl(al); printColl(al1); } // public static void printColl(ArrayList<String> al) //ArrayList<String> al = new ArrayList<Integer>(); Error public static void printColl(ArrayList<?> al) //ArrayList<?> al = new ArrayList<Integer>(); { Iterator<?> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } */ class Person { private String name; Persion(String name) { this.name = name; } public String getName() { return name; } } class Student extends Person { Student(String name) { super(name); } } public static void main(String[] args) { ArrayList<Person> al = new ArrayList<Person>(); al.add(new Person("abc01")); al.add(new Person("abc02")); al.add(new Person("abc03")); ArrayList<Student> al1 = new ArrayList<Student>(); al1.add(new Student("abc01")); al1.add(new Student("abc02")); al1.add(new Student("abc03")); printColl(al); //ArrayList<Person> al = new ArrayList<Student>(); } public static void printColl(ArrayList<? extends Person> al) //限定?可接受的类型范围,只能打印Person和Person的子类 { Iterator<? extends Person> it = al.iterator(); //这里只能打印Person和Person的子类 while(it.hasNext()) { System.out.println(it.next().getName()); } } } /* 泛型限定2--下限应用 */ import java.util.*; class GenericDemo8 { public static void main(String[] args) { /* TreeSet<Student> ts = new TreeSet<Student>(new StuComp()); ts.add(new Student("abc01"); ts.add(new Student("abc02"); ts.add(new Student("abc03"); Iterator<Student> it = ts.iterator(); while(it.hasNext()) { System.out.println(it.next().getName()); } TreeSet<Worker> ts1 = new TreeSet<Worker>(new WorkComp()); ts1.add(new Worker("abc-01"); ts1.add(new Worker("abc-02"); ts1.add(new Worker("abc-03"); Iterator<Worker> it1 = ts1.iterator(); while(it1.hasNext()) { System.out.println(it1.next().getName()); } */ TreeSet<Student> ts = new TreeSet<Student>(new Comp()); ts.add(new Student("abc01"); ts.add(new Student("abc02"); ts.add(new Student("abc03"); Iterator<Student> it = ts.iterator(); while(it.hasNext()) { System.out.println(it.next().getName()); } TreeSet<Worker> ts1 = new TreeSet<Worker>(new Comp()); ts1.add(new Worker("abc-01"); ts1.add(new Worker("abc-02"); ts1.add(new Worker("abc-03"); Iterator<Worker> it1 = ts1.iterator(); while(it1.hasNext()) { System.out.println(it1.next().getName()); } } } /* class StuComp implements Comparator<Student> //Student的比较器 { public int compare(Student s1,Student s2) { return s1.getName().compareTo(s2.getName()); } } class WorkComp implements Comparator<Worker> //Worker的比较器 { public int compare(Worker w1,Worker w2) { return w1.getName().compareTo(w2.getName()); } } */ //以上没比较一个对象需要创建一个比较器,非常麻烦 class Comp implements Comparator<Person> { public int compare(Person p1,Person p2) { return p1.getName().compareTo(p2.getName()); } } class Person { private String name; Person(String name) { this.name = name; } public String getName() { return name; } public String toString() { return "Person: " + name; } } class Student extends Person { Student(String name) { super(name); } } class Worker extends Person { Worker(String name) { super(name); } } /* Map集合,集合存储的是键值对,必须要保证键的唯一性 1.添加 put(K key,V value); putAll(Map<? extends K,? extends V>m); 2.删除 clear(); remove(Object key); 3.判断 containsValue(Object value); containsKey(Object key); isEmpty(); 4.获取 get(Object key); size(); values(); entrySet(); keySet(); Map:Map和Set很像,Set底层就是使用的Map集合 |--Hashtable:底层是哈希表数据结构,不可以存入null键或者null值,该集合是线程同步的 |--HashMap:底层是哈希表数据结构,并允许使用null键或null值,该集合是不同步的 |--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键排序 */ //Map的共性方法 import java.util.*; class MapDemo1 { public static void main(String[] args) { //添加元素,如果出现相同的键,那么后添加的值会覆盖原有的键对应的值,put方法会返回原有的值 Map<String,String> map = new HashMap<String,String>(); map.put("01","zhangsan01"); map.put("02","zhangsan02"); map.put("03","zhangsan03"); //判断 System.out.println("containsKey:" + map.containsKey("02")); //移除 System.out.println("remove:" + map.remove("03")); System.out.println(map); //获取 System.out.println("get:" + map.get("02")); map.put("04",null); System.out.println("get:" + map.get("04"));//可以通过get方法的返回值来判断一个键是否存在 //获取map集合中的所有值 Collection<String> coll = map.values(); System.out.println(coll); System.out.println(map); } } /* Map集合的两种取出方式: 1. Set<key> keySet:将Map中所有的键存入到Set集合中,因为Set集合具备迭代器。 所以可以通过迭代方式取出所有的键,然后再根据get方法,获取每一个键对应的值。 map集合的取出原理:将map集合转换成set集合,再通过迭代器取出 */ import java.util.*; class MapDemo2 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("01","zhangsan01"); map.put("02","zhangsan02"); map.put("03","zhangsan03"); map.put("04","zhangsan04"); //先获取map集合中的所有键的set集合,keySet(); Set<String> keySet = map.keySet(); //有了Set集合就可以获取其迭代器 Iterator<String> it = keySet.iterator(); while(it.hasNext()) { String key = it.next(); //有了键就可以通过map集合的get方法获取其对应的值 String value = map.get(key); System.out.println("key:" + key + ",value:" + value); } } } /* 2. Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry Map.Entry相当于一个关系类型,获取到Map.Entry对象后就可以通过Map.Entry中的getKey和getValue方法获取键和值 */ import java.util.*; class MapDemo3 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("01","zhangsan01"); map.put("02","zhangsan02"); map.put("03","zhangsan03"); map.put("04","zhangsan04"); Set<Map.Entry<String,String>> entrySet = map.entrySet(); Iterator<Map.Entry<String,String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<String,String> me = it.next(); String key = me.getKey(); //getKey方法获取关系映射中的键 String value = me.getValue(); //getValue方法获取关系映射中的值 System.out.println(key + ":" + value); } } } /* Map.Entry其实Entry也是一个接口,它是Map接口中的一个内部接口 它是通过内部类实现的 */ interface Map { public static interface Entry { public abstract Object getKey(); public abstract Object getValue(); } } class HashMap implements Map .Entry { class Haha implements Map.Entry { public Object getKey() { } public Object getValue() { } } } /* Map练习 每一个学生都有对应的归属地 学生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 int compareTo(Student s) //重写比较器 { int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num==0) return this.name.compareTo(s.name); return num; } public int hashCode() { return name.hashCode() + age * 34; } public boolean equals(Object obj) //重写equals方法 { if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.age == s.age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name + ":" + age; } } class MapTest1 { public static void main(String[] args) { HashMap<Student,String> hm = new HashMap<Student,String>(); hm.put(new Student("lisi1",21),"beijing"); hm.put(new Student("lisi2",22),"shanghai"); hm.put(new Student("lisi3",23),"tianjin"); hm.put(new Student("lisi4",24),"chengdu"); //第一种取出方式keySet 第一种取出方式keySet hash表示无序的 Set<Student> keySet = hm.keySet(); Iterator<Student> it = hm.keySet().iterator(); while(it.hasNext()) { Student stu = it.next(); String addr = hm.get(stu); System.out.println(stu + " keySet: " + addr); } //第二种取出方式entrySet 第一种取出方式entrySet Set<Map.Entry<Student,String>> entrySet = hm.entrySet(); Iterator<Map.Entry<Student,String>> iter = entrySet.iterator(); while(iter.hasNext()) { Map.Entry<Student,String> me = iter.next(); Student stu = me.getKey(); String addr = me.getValue(); System.out.println(stu + " entrySet: " + addr); } } } /* TreeMap练习 需求:对学生对象的年龄进行升序排序 因为数据是以键值对形式存在的 所以要使用可以排序的Map集合.TreeMap */ 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 int compareTo(Student s) //重写比较器 { int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num==0) return this.name.compareTo(s.name); return num; } public int hashCode() { return name.hashCode() + age * 34; } public boolean equals(Object obj) //重写equals方法 { if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.age == s.age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name + ":" + age; } } class StuNameComparator 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())); //次要条件 return num; } } class MapTest2 { public static void main(String[] args) { TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator()); tm.put(new Student("lisi1",21),"beijing"); tm.put(new Student("lisi2",22),"shanghai"); tm.put(new Student("lisi3",23),"tianjin"); tm.put(new Student("lisi4",24),"chengdu"); Set<Map.Entry<Student,String>> entrySet = tm.entrySet(); Iterator<Map.Entry<Student,String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<Student,String> me = it.next(); Student stu = me.getKey(); String addr = me.getValue(); System.out.println(stu + ":::" + addr); } } } /* map集合扩展知识:map集合被使用是因为具备映射关系 集合嵌套应用 一个学校有多个教室,每个教室都有名称 学校 |--教室1 |--01,zhangsan |--02,lisi |--教室2 |--01,wangwu |--02,zhaoliu */ import java.util.*; class MapExtend { public static void main(String[] args) { HashMap<String,HashMap<String,String>> school = new HashMap<String,HashMap<String,String>>(); //创建学校 HashMap<String,String> classroom1 = new HashMap<String,String>(); //创建教室1 HashMap<String,String> classroom2 = new HashMap<String,String>(); //创建教室2 school.put("classroom1",classroom1); //1对多 school.put("classroom2",classroom2); //1对多 classroom1.put("01","zhangsan"); //向教室添加学生 classroom1.put("02","lisi"); //向教室添加学生 classroom2.put("01","wangwu"); //向教室添加学生 classroom2.put("02","zhaoliu"); //向教室添加学生 //变量学校集合,获取所有教室 Iterator<String> it = school.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); HashMap<String,String> room = school.get(roomName); getStudentInfo(room); //获取所有教室的学生 } } public static void getStudentInfo(HashMap<String,String> roomMap) { Iterator<String> it = roomMap.keySet().iterator(); while(it.hasNext()) { String id = it.next(); String name = roomMap.get(id); System.out.println(id + ":" + name); } } } /* 集合框架的工具类 Collections-binarySearch Collections-max Collections-sort */ import java.util.*; class CollectionsDemo1 { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("qq"); list.add("q"); sop(list); int index = halfSearch2(list,"zz",new StrLenComparator()); } public static void binarySearchDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("qq"); list.add("q"); sop(list); Collections.sort(list); sop(list); int index = Collections.binarySearch(list,"aaa"); //二分查找 sop("index=" + index); } public static int halfSearch(List<String> list,String key) //binarySearch原理 { int max,min,mid; max = list.size()-1; min = 0; while(min<=max) { mid = (max+min)>>1; // /2 String str = list.get(mid); int num = str.compareTo(key); if(num>0) max = mid - 1; else if(num<0) min = mid + 1; else return mid; } return -min-1; } public static int halfSearch2(List<String> list,String key,Comparator<String> comp) //binarySearch原理带比较器 { int max,min,mid; max = list.size()-1; min = 0; while(min<=max) { mid = (max+min)>>1; // /2 String str = list.get(mid); int num = comp.compare(str,key) if(num>0) max = mid - 1; else if(num<0) min = mid + 1; else return mid; } return -min-1; } public static void maxDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("qq"); list.add("q"); sop(list); String max = Collections.max(list); //取最大值 sop("max:" + max); } public static void sortDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("qq"); list.add("q"); sop(list); Collections.sort(list,new StrLenComparator()); //给list集合排序 sop(list); } public static void sop(Object obj) { System.out.println(obj); } } class StrLenComparator implements Comparator<String> //实现比较器 { public int compare(String s1,String s2) { if(s1.length()>s2.length()) return 1; if(s1.length()<s2.length()) return -1; return s1.compareTo(s2) } } /* Collections-替换反转 */ import java.util.*; class CollectionsDemo2 { public static void main(String[] args) { } public static void replaceAllDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); sop(list); Collections.replaceAll(list,"aaa","www"); //替换 Collections.reverse(list); //反转 sop(list); } /* fill方法可以将list集合中的所有元素替换成指定元素 练习:将list集合中的部分元素替换成指定元素 */ public static void fillDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); sop(list); Collections.fill(list,"pp"); //将集合中的元素全部替换成"pp" sop(list); } public static void sop(Object obj) { System.out.println(obj); } } /* Collections-reverseOrder 逆向比较器 reverseOrder还可以强行逆向指定比较器 */ import java.util.*; class CollectionsDemo3 { public static void main(String[] args) { reverseOrderDemo(); } public static void reverseOrderDemo() { //TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder()); //传入逆向比较器 TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator())); //逆向指定比较器 ts.add("abcd"); ts.add("aaa"); ts.add("zz"); ts.add("kkkkk"); Iterator it = ts.iterator(); while(it.hasNext()) { sop(it.next()); } } public static void sop(Object obj) { System.out.println(obj); } } class StrLenComparator implements Comparator<String> //实现比较器 { public int compare(String s1,String s2) { if(s1.length()>s2.length()) return 1; if(s1.length()<s2.length()) return -1; return s1.compareTo(s2); } } /* Collections-swap //置换 Collections-shuffle //随机置换 */ import java.util.*; class CollectionsDemo2 { public static void main(String[] args) { swapDemo(); } public static void swapDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); sop(list); Collections.swap(list,1,2); //指定角标置换 sop(list); } public static void shuffleDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); sop(list); Collections.shuffle(list); //随机置换 sop(list); } public static void sop(Object obj) { System.out.println(obj); } } /* 集合框架工具类Arrays,用于操作数组的工具类 里面都是静态方法 asList: 将数组转换为List集合 */ import java.util.*; class ArraysDemo { public static void main(String[] args) { // int[] arr = {2,4,5}; // System.out.println(Arrays.toString(arr)); String[] arr = {"abc","cc","kkkk"}; /* 把数字变成集合的好处: 可以使用集合的思想和方法来操作数组中的元素 注意:将数组变为集合,不可以使用集合的增删方法 因为数组的长度是固定的 */ List<String> list = Arrays.asList(arr); //将数组转换为List集合 //list.add("qq"); //UnsupportedOperationException System.out.println(list); /* 如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素 如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。 */ int[] nums = {2,4,5}; List<int[]> li = Arrays.asList(nums); //这里泛型要指定int[]数组类型才行 System.out.println(li); } } /* 集合变数组 Collection接口中的toArray方法 */ import java.util.*; class CollectionToArrayDemo { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc01"); al.add("abc02"); al.add("abc03"); /* 1.指定类型的数组到底要定义多长呢? 当指定类型的数组长度小于了集合的size,那么该方法的内部会创建一个新的数组,长度为集合的size。 当指定类型的数组长度大于了集合的size,那么就不会新创建数组,而是使用传递进来的数组 所以创建一个刚刚好的数组最为合适 2.为什么要将集合变数组? 为了限定对元素的操作.如果你把集合返回给对方,对方依然可以对集合进行增删 而如果你把集合转成数组返回去,那么数组的长度是固定的,对方就无法对集合进行增删 */ String[] arr = al.toArray(new String[al.size()]); //保证数组长度刚刚好 System.out.println(Arrays.toString(arr)); } } /* 高级for循环 格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) { 只能获取集合元素,但是不能对集合进行操作 迭代器除了遍历,还可以进行remove集合中的元素的动作 如果是用了ListIterator,还可以在遍历过程中对集合进行增删改查的动作 } */ import java.util.*; class ForEachDemo { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc01"); al.add("abc02"); al.add("abc03"); /* Iterator<String> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next()); } */ /* JDK1.5以后可以用for循环遍历集合 底层还是用的迭代器,为了简化书写 */ for(String s : al) //s第一次指向了集合中的第一个元素 { s = "kk"; System.out.println(s); } System.out.println(al); //以上循环其实是有局限性的,它只能对集合中的元素做取出,而不能做修改操作 /* 传统for循环和高级for循环有什么区别呢? 高级for循环有一个局限性,必须有被遍历的目标。 建议在遍历数组的时候,还是希望是用传统的for,因为传统的for循环可以定义角标 */ int[] arr = {3,5,1}; for(int i : arr) { System.out.println("i:" + i); } HashMap<Integer,String> hm = new HashMap<Integer,String>(); hm.put(1,"a"); hm.put(2,"b"); hm.put(3,"c"); Set<Integer> keySet = hm.keySet(); for(Integer i : keySet) { System.out.println(i+ "::" + hm.get(i)); } //上面的简写形式 for(Map.Entry<Integer,String> me : hm.entrySet()) { System.out.println(me.getKey()+"---"+me.getValue()); } } } /* JDK1.5版本以后出现的新特性-可变参数 方法的可变参数,在使用时注意: 可变参数一定要定义在参数列表的最后面 */ class ParamMethodDemo { public static void main(String[] args) { /* int[] arr = {3,4}; show(arr); int[] arr1 = {2,3,5,6}; show(arr1); */ show("hell world",2,3,4,5); } //很麻烦,多一个参数重载一次 /* public static void show(int a,int b) { System.out.println(a+","+b); } public static void show(int a,int b,int c) { } */ //用数组还不麻烦,因为每次要new一个数组 /* public static void show(int[] arr) { } */ /* 其实这种方法还是数组,但是我们省去了new数组的操作 这种方法叫可变参数 */ public static void show(String str,int... arr) //可变参数一定要定义在参数列表的最后面 { System.out.println(arr.length); //这里arr是一个数组,长度是你传入的值 } } /* 静态导入 当类名重名时,需要指定具体的包名 当方法重名时,需要指定具备所属的对象或者类 */ import java.util.*; import static java.util.Arrays.*; //导入的是Arrays这个类中的所有静态成员 import static java.lang.System.*; //导入了System类中的所有静态成员. class StaticImport { public static void main(String[] args) { int[] arr = {3,1,5}; /* Arrays.sort(arr); int index = Arrays.binarySearch(arr,1); System.out.println(Arrays.toString(arr)); System.out.println("Index=" + index); */ /* 导入静态成员后就可以不用再写类名. */ sort(arr); int index = binarySearch(arr,1); System.out.println(Arrays.toString(arr)); //这里方法重名,所以不能省略 System.out.println("Index=" + index); out.println("Hello World"); //省略System. } }