java08 Set
Set: 无序不可重复,重复则覆盖,判断是不是重复也是通过equals方法判断的。HashSet和TreeSet,HashSet底层是HashMap。 public static void main(String[] args) { Set set = new HashSet(); set.add("aaa"); set.add("bbb"); set.add(new String("aaa")); System.out.println(set.size()); System.out.println(set.contains("aaa")); set.remove("aaa"); } 自己实现一个Set(Set底层用的Map): public class SxtHashSet { HashMap map; private static final Object PRESENT = new Object(); public SxtHashSet(){ map = new HashMap(); } public int size(){ return map.size(); } public void add(Object o){ map.put(o, PRESENT); //set的不可重复就是利用了map里面键对象的不可重复!value是固定值。 } public static void main(String[] args) { SxtHashSet s = new SxtHashSet(); s.add("aaa"); s.add(new String("aaa"));//重复就替换了。 System.out.println(s.size()); } } List<Map> list = new ArrayList<Map>(); List<Employee> list = new ArrayList<Employee>(); (内部类可以直接使用外部类的方法和属性) List和set都有Interetar方法: public boolean hasNext() { return cursor != size();//直到cursor=size()则为false,没有下一个了。 } public E next() { checkForComodification(); try { E next = get(cursor);//返回这个值 lastRet = cursor++;//返回之后游标++,lastRet指向刚刚遍历完的对象。 return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet);//移除刚刚遍历的对象。 if (lastRet < cursor) cursor--;//游标自减 lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } 遍历集合: public static void main(String[] args) { List list = new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); //通过索引遍历List for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } //通过迭代器遍历List for(Iterator iter2 = list.iterator();iter2.hasNext();){//hasNext()判断是否有下一个。 String str = (String) iter2.next();//next()返回当前游标指向的对象。 System.out.println(str); iter2.remove();//删除游标左边的元素,在执行next()之后该操作只能执行一次。 iter2.remove(); } System.out.println(list.size()+"******"); Set set = new HashSet(); set.add("高1"); set.add("高2"); set.add("高3"); //通过迭代器遍历Set Iterator iter = set.iterator(); while(iter.hasNext()){ for(Iterator iter1 = set.iterator();iter.hasNext();){ String str = (String) iter1.next(); System.out.println(str); } } } 遍历Map: public static void main(String[] args) { Map map = new HashMap(); map.put("aa", "aaaa"); map.put("bb", "bbbb"); //遍历Map的第一种方式 Set keys = map.keySet(); for(Iterator iter = keys.iterator();iter.hasNext();){ String keyStr = (String) iter.next(); System.out.println(keyStr+"---"+map.get(keyStr)); } //遍历Map的第二种方式 Set<Entry> set2 = map.entrySet(); for(Iterator iter = set2.iterator();iter.hasNext();){ Entry e = (Entry) iter.next(); System.out.println(e.getKey()+"---"+e.getValue()); } }
泛型: 所有的强制转换都是自动的和隐式的(如果用Object来替代的话,就要写强制转换的代码)。 /* 泛型类:声明时使用泛型 字母(随便写U,C,A): T Type 表示类型。 K V 分别代表键值中的Key Value。 E 代表Element。 ?表示不确定类型。 使用时确定类型 注意: 1、泛型只能使用引用类型,不能基本类型(不能传int进来,可以使用Integer。) 2、泛型声明时字母不能使用 静态属性|静态方法上*/ public class Student<T1,T2> { private T1 javaScore; private T2 oracleScore; //泛型声明时不能使用 静态属性|静态方法上 private static T1 test; public T1 getJavaScore() { return javaScore; } public void setJavaScore(T1 javaScore) { this.javaScore = javaScore; } public T2 getOracleScore() { return oracleScore; } public void setOracleScore(T2 oracleScore) { this.oracleScore = oracleScore; } public static void main(String[] args) { //使用时指定类型(引用类型) Student<String,Integer> stu = new Student<String,Integer> (); //1、安全:编译时有类型检查 stu.setJavaScore("优秀"); //2、省心:类型强制转换自动进行 int it =stu.getOracleScore(); //自动拆箱 } } /** * 接口中 泛型字母只能使用在方法中,不能使用在全局常量(接口中的常量都是静态的)中 * @author Administrator * * @param <T> */ public interface Comparator<T> { void compare(T t); } public static void main(String[] args) { test("a"); //T -->String } //泛型方法 public static <T> void test(T a){ //方法里面不能操作a,因为a的类型都不确定。只能访问a. System.out.println(a); } // extends <=,T extends Closeable表示T只能是Closeable的实现类(子类) public static <T extends Closeable> void test(T... a){ for(T temp:a){// try { if(null!=temp){ temp.close(); } } catch (IOException e) { e.printStackTrace(); } } } } /** 父类为泛型类 1、属性 2、方法 要么同时擦除,要么子类大于等于父类的类型。 不能子类擦除,父类仍为泛型。 1、属性类型 父类中,随父类而定 子类中,随子类而定 2、方法重写: 里面都是父类的类型。 */ public abstract class Father<T,T1> { T name; public abstract void test(T t); } /** * 子类声明时指定具体类型(类定义时指定类型,也就是大于等于) * 属性类型为具体类型 * 方法同理 */ class Child1 extends Father<String,Integer>{ String t2; @Override public void test(String t) { } } /** * 子类为泛型类 ,类型在使用时确定 * @author Administrator * */ class Child2<T1,T,T3> extends Father<T,T1>{//也是大于等于 T1 t2; @Override public void test(T t) { } } /** * 子类为泛型类,父类不指定类型 即泛型的擦除,父类擦除后是Object类型。 */ class Child3<T1,T2> extends Father{ T1 name2; @Override public void test(Object t) {//方法重写后里面的类型随父类而定,此时为Object不是T。 } } /** * 子类与父类同时擦除,擦除后类型就是Object。 */ class Child4 extends Father{ String name; @Override public void test(Object t) { } } //错误:子类擦除,父类使用泛型 class Child5 extends Father<T,T1>{ String name; @Override public void test(T t) { } } /** *泛型的擦除 *1、继承|实现声明 不指定类型 *2、使用时 不指定类型 *统一Object 对待 *1、编译器警告 消除使用Object *2、不完全等同于Object ,编译不会类型检查 * @author Administrator * * @param <T> */ public class Student<T> { private T javaScore; private T oracleScore; //泛型声明时不能使用 静态属性|静态方法上 //private static T1 test; public T getJavaScore() { return javaScore; } public void setJavaScore(T javaScore) { this.javaScore = javaScore; } public T getOracleScore() { return oracleScore; } public void setOracleScore(T oracleScore) { this.oracleScore = oracleScore; } /** * @param args */ public static void main(String[] args) { Student stu1 = new Student(); //消除警告 使用 Object Student<Object> stu = new Student<Object>(); //stu.setJavaScore("af"); //以Object对待 test(stu1); //stu1 相当于Object 但是不完全等同Object //擦除,不会类型检查 //test(stu); test1(stu1); test1(stu); } public static void test(Student<Integer> a){ } public static void test1(Student<?> a){ } } /** * 泛型接口:与继承同理 * 重写方法类型随父类而定 */ public interface Comparable<T> { void compare(T t); } //声明子类指定具体类型 class Comp implements Comparable<Integer>{ @Override public void compare(Integer t) {//方法的重写时,类型跟父类一样。 } } //同时擦除,方法重写为Object。 class Comp1 implements Comparable{ @Override public void compare(Object t) { } } //父类擦除,子类泛型 class Comp2<T> implements Comparable{ @Override public void compare(Object t) {//方法重写时类型随父类,此时为object } } //子类泛型>=父类泛型 class Comp3<T> implements Comparable<T>{ @Override public void compare(T t) { } } //父类泛型,子类擦除 错误 类与接口存在多态。 泛型没有多态,直接使用A<Object> a = new A<String>()是错误的,方法形参和返回值类型也不存在泛型多态。不能使用a instanceof A<String>判断是否为泛型实例。要实现多态就是通过通配符?,?extends super.可以用在声明类型和声明方法的参数上,不能用在声明类上,?可以接受泛型的任意类型,只能接收和输出,不能修好(方法申明时参数不能知道具体的类型,因此不能修改),?extends 泛型上限,?super 泛型下限。 public class A<?> {//错误 } public class Fruit { } class Apple extends Fruit{ } //泛型类 public class A<T> { } public static void main(String[] args) { A<Fruit> f0 = new A<Apple>();//错误,泛型没有多态。 A<Fruit> f =new A<Fruit>();//正确,一定要类型一样 //test(new A<Apple>()); } //返回类型使用多态 public static A<Fruit> test2(){ return (A<Fruit>)(new A<Apple>());//错误, return null; } /** * 通配符 * ?声明时类型不定,使用时确定类型 * * ?使用:声明类型|声明方法上,不能声明类也不能使用时用? * * ? extends : <= 上限 指定类型 子类或自身 * * ? super :>=下限 指定类型 为自身或父类 */ public class Student<T> { T score; public static void main(String[] args) { Student<?> stu = new Student<String>();//Student<?> stu声明时用?表示类型不定,new Student<String>()使用时确定类型, test(new Student<Integer>());//使用了?所以可以传进去 test2(new Student<Apple>());//使用了?所以可以传进去 test3(new Student<Apple>()); //错误,没有使用?,所以传不进去,泛型没有多态 test4(new Student<Apple>()); //错误,小于了 stu = new Student<Fruit>(); test4(stu); //错误,编译的时候看左边,Student<?> stu所以不行。 test4(new Student<Object>()); test4(new Student<Fruit>()); } public static void test(Student<?> stu){ } public static void test3(Student<Fruit> stu){ } // <= public static void test2(Student<? extends Fruit> stu){//? extends Fruit传进去的类型为Fruit的子类, } //>= public static void test4(Student<? super Fruit> stu){ } } 泛型的嵌套: A<B<C>> a = new A<B<C>>();使用时从外到内一层层拆分。 public class Bjsxt <T>{ T stu ; public static void main(String[] args) { //泛型的嵌套 Bjsxt<Student<String>> room = new Bjsxt<Student<String>>(); //从外到内一层层拆分 room.stu = new Student<String>(); Student<String> stu = room.stu; String score =stu.score; System.out.println(score); } } public class Student<T> { T score; } 泛型与数组: 没有泛型数组,不能创建泛型数组(不能开辟空间)。可以使用?声明。 /** * 没有泛型数组 * 声明可以使用,但是创建失败 * @author Administrator * */ public class Array { /** * @param args */ public static void main(String[] args) { Integer[] arr = new Integer[4]; Student<String>[] arr20 = new Student<String>[10];//左边声明可以,右边创建就报错,?只能用在声明中,所以没有泛型数组。 Student<?>[] arr2 = new Student[10];//正确 MyArrayList<String> strList =new MyArrayList<String>(); strList.add(0, "a"); String elem =strList.getElem(0); System.out.println(elem); ArrayList l; } } class MyArrayList<E>{ E[] cap0 =new E[10];//错误, 没有泛型数组,右边不能开辟空间,因为指定不了长度。 Object[] cap = new Object[10];//里面使用Object数组接收,jdk源码也是用Object数组接收, public void add(int idx,E e){ cap[idx] =e; } @SuppressWarnings("unchecked") public E[] getAll(){ return (E[]) cap;//返回的时候要转换为E类型,jdk源码也是这种写法。 } @SuppressWarnings("unchecked") public E getElem(int idx){ return (E) cap[idx]; } } //jdk泛型的源码: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; private transient Object[] elementData; private int size; public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public ArrayList() { this(10); } public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } public E get(int index) { RangeCheck(index); return (E) elementData[index];//也要转换为泛型 } } public static void main(String[] args) { List<String> arrList= new ArrayList<String>();//1.6也正确 List<String> arrList2= new ArrayList<>();//1.7正确,在使用|创建时不用指定类型,相当于声明一次类型即可。 } 简化迭代器原理: public class MyArrayList { private String[] elem ={"a","b","c","d","e","f","g"}; private int size = elem.length; private int cursor =-1;//数组的下标为0,在0之前所以为-1, /** * 判断是否存在下一个元素 * @return */ public boolean hasNext(){//当前游标的下一个元素是不是在这个范围内。 return cursor+1<size; } /** * 获取下一个元素 */ public String next(){ cursor++; //移动一次 return elem[cursor]; } /** * 删除元素 */ public void remove(){ } /** * @param args */ public static void main(String[] args) { MyArrayList list = new MyArrayList(); while(list.hasNext()){ System.out.println(list.next()); } list = new MyArrayList(); while(list.hasNext()){ System.out.println(list.next()); } } } 另一种实现: public class MyArrayList2 { private String[] elem ={"a","b","c","d","e","f","g"}; private int size = elem.length; private class MyIt implements Iterator<String>{//内部类可以访问外部类的属性和方法,jdk的底层也是用内部类实现的。 private int cursor =-1; /** * 判断是否存在下一个元素 * @return */ public boolean hasNext(){ return cursor+1<size; } /** * 获取下一个元素 */ public String next(){ cursor++; //移动一次 return elem[cursor]; } /** * 删除元素 */ public void remove(){ //没有实现 } } public Iterator<String> iterator(){ return new MyIt(); } /** * @param args */ public static void main(String[] args) { MyArrayList2 list = new MyArrayList2(); Iterator<String> it =list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } it =list.iterator();//每次调用iterator方法,cursor都归为-1,如果cursor写在外面则下次调用iterator方法时cursor不能归为-1而是最大值。 while(it.hasNext()){ System.out.println(it.next()); } } } 另一种实现: public class MyArrayList3 implements java.lang.Iterable<String> { private String[] elem ={"a","b","c","d","e","f","g"}; private int size = elem.length; /** * 匿名内部类 * @return */ public Iterator<String> iterator(){ return new Iterator<String>(){//new一个接口的对象。 private int cursor =-1; /** * 判断是否存在下一个元素 * @return */ public boolean hasNext(){ return cursor+1<size; } /** * 获取下一个元素 */ public String next(){ cursor++; //移动一次 return elem[cursor]; } /** * 删除元素 */ public void remove(){ //没有实现 } }; } public static void main(String[] args) { MyArrayList3 list = new MyArrayList3(); Iterator<String> it =list.iterator(); while(it.hasNext()){ System.out.println(it.next()); it.remove(); //正确,迭代器可以在查看的时候删除元素。 } it =list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } System.out.println("增强for,必须实现java.lang.Iterable接口,重写iterator方法"); for(String temp:list){//增强for里面不能有删除 System.out.println(temp); temp.remove();//错误,增强for里面不能有删除 } } } HashMap: Map里面的键是不能重复的,因为就是一个Set,Set是不能重复的。 /** * this is a cat and that is a mice and where is the food? * 统计每个单词出现的次数 * * 存储到Map中 * key :String * value:自定义类型 * * "分拣" 思路 * 1、为所有key创建容器 * 之后容器中存放对应value * 2、第一次创建容器,并存放值value * 第二次之后,直接使用容器存放值 * @author Administrator * */ public class Demo01 { /** * @param args */ public static void main(String[] args) { String str ="this is a cat and that is a mice and where is the food"; //分割字符串 String[] strArray = str.split(" "); //存储到Map中 Map<String,Letter> letters = new HashMap<String,Letter>(); for(String temp:strArray){ //法1-------------------------------------------------------------- //1、为所有key创建容器 if(!letters.containsKey(temp)){ Letter col = new Letter(); col.setCount(1); //第一次值存放容器中 letters.put(temp, col); }else{ //2、 第二次之后,直接使用容器存放值 Letter col =letters.get(temp); //直接使用容器 col.setCount(col.getCount()+1); } //法2-------------------------------------------------------------- Letter col = null; if(null==(col=letters.get(temp))){ col = new Letter(); col.setCount(1); //第一次值存放容器中 letters.put(temp, col); }else{ //2、 第二次之后,直接使用容器存放值 col.setCount(col.getCount()+1); } } //输出Map的值 Set<String> keys = letters.keySet(); for(String key:keys){ Letter col =letters.get(key); System.out.println("字母:"+key+",次数"+col.getCount()); } } public static void test1(){ String str ="this is a cat and that is a mice and where is the food"; //分割字符串 String[] strArray=str.split(" "); //存储到Map中 Map<String,Letter> letters = new HashMap<String,Letter>(); /* for(String temp:strArray){ //1、为所有key创建容器 之后容器中存放对应value if(!letters.containsKey(temp)){ letters.put(temp, new Letter()); } } for(String temp:strArray){ // 容器中存放对应value Letter col =letters.get(temp); //直接使用容器 col.setCount(col.getCount()+1); } */ for(String temp:strArray){ //1、为所有key创建容器 if(!letters.containsKey(temp)){ letters.put(temp, new Letter()); } //2、 之后容器中存放对应value Letter col =letters.get(temp); //直接使用容器 col.setCount(col.getCount()+1); } //输出Map的值 Set<String> keys = letters.keySet(); for(String key:keys){ Letter col =letters.get(key); System.out.println("字母:"+key+",次数"+col.getCount()); } } } /** * 定义一个Student类,属性:name 姓名,classNumber 班号,score 成绩 现在将若干Student对象放入List,请统计出每个班级的总分和平均分,分别打印出来 以面向对象的思维解决 * @author Administrator * */ public class MapDemo03 { public static void main(String[] args) { List<Student> list = new ArrayList<Student>(); exam(list); //统计 Map<String,ClassRoom> rooms = new HashMap<String,ClassRoom>(); count(rooms,list); //打印 printScore(rooms); } /** * 打印 总分与平均分 */ public static void printScore(Map<String,ClassRoom> rooms){ Set<Map.Entry<String,ClassRoom>> entrySet =rooms.entrySet(); Iterator<Map.Entry<String,ClassRoom>> it =entrySet.iterator(); while(it.hasNext()){ Map.Entry<String,ClassRoom> entry =it.next(); ClassRoom room = entry.getValue(); double avg = room.getTotal()/room.getStus().size(); System.out.println("班号为:"+room.getNo()+",总分"+room.getTotal()+",平均分"+avg); } } /** * 统计分数 */ public static void count(Map<String,ClassRoom> rooms,List<Student> list){ for(Student stu:list){ String no = stu.getNo(); double score = stu.getScore(); //根据班级编号 查看 Map是否存在该班级 分拣思路 ClassRoom room = rooms.get(no); if(null==room){ //第一次 room = new ClassRoom(no); rooms.put(no, room); } //存储 总分 room.setTotal(room.getTotal()+score); room.getStus().add(stu); //加入学生 } } /** * 现在将若干Student对象放入List * @param list */ public static void exam(List<Student> list){ list.add(new Student("a","001",80)); list.add(new Student("b","001",80)); list.add(new Student("a","002",80)); list.add(new Student("c","003",80)); list.add(new Student("d","003",80)); } } 排序: 基本数据类型如int就是大小排序。 引用类型,如果是内置类,则内部已经指定规则,直接使用即可。如果是自定义类,则按照业务规则排序。 顺序:升序、降序。 排列算法:冒泡,选择,插入, shell ,堆 等等。 冒泡排序: public class BubbleSort1 { public static void main(String[] args) { int[] arr ={9,8,7,6,5}; sort(arr); } //第一版本,很简单 public static void sort(int[] arr){ int len =arr.length; for(int j=0;j<len-1;j++){ System.out.println("第"+(j+1)+"趟"); for(int i=0;i<len-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } } } public static void sortSecond(int[] arr){ System.out.println("第一趟"); for(int i=0;i<arr.length-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } System.out.println("第二趟"); for(int i=0;i<arr.length-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } System.out.println("第三趟"); for(int i=0;i<arr.length-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } System.out.println("第四趟"); for(int i=0;i<arr.length-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } } public static void sortFirst(int[] arr){ System.out.println("第一趟"); for(int i=0;i<arr.length-1;i++){ System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } /* //第一趟 第一次 System.out.println("第一趟 第一次"); int i=0; if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); System.out.println("第一趟 第二次"); i++; if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); System.out.println("第一趟 第三次"); i++; if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); System.out.println("第一趟 第四次"); i++; if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); */ } } public static void main(String[] args) { int[] arr ={9,8,7,6,5}; sort(arr); } //第二版本,减少每一趟的次数 public static void sort(int[] arr){ int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 System.out.println("第"+(j+1)+"趟"); for(int i=0;i<len-1-j;i++){ //次数 System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } } } public class BubbleSort { /** * @param args */ public static void main(String[] args) { int[] arr ={1,2,9,3,4}; sort1(arr); System.out.println("==========final============"); arr =new int[]{9,1,2,3,4}; sortFinal(arr); } //第二版本,减少每一趟的次数 public static void sortFinal(int[] arr){ boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } System.out.println(Arrays.toString(arr)); } if(sorted){ //减少趟数 break; } } } //第二版本,减少每一趟的次数 public static void sort1(int[] arr){ int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 System.out.println("第"+(j+1)+"趟"); for(int i=0;i<len-1-j;i++){ //次数 System.out.print("第"+(i+1)+"次"); if(arr[i]>arr[i+1]){ int temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; } System.out.println(Arrays.toString(arr)); } } } } 冒泡排序用的是基本数据类型,下面比较引用类型: 排序的实体类都实现了Comparable接口,里面只有一个方法compareTo方法,实现了Comparable接口的类通过实现compareTo方法从而确定该类对象的排序方式。正数表示this>obj,负数表示this<obj。 引用数据类型:jdk自带的类,自己定义的类。 内置引用数据类型(常用)的比较,源码有比较方法重写了compareTo方法。 public static void main(String[] args) { Integer a ; //根据基本数据类型大小,源码有重写 Character ch; //根据Unicode编码顺序 String str="abcd1233333"; //如果其中一个是另外一个起始开始的子串,返回长度之差 String str2 ="abc"; //否则返回第一个不相等的字符的unicode码之差 System.out.println(str.compareTo(str2));//8 str ="abc"; str2 ="aed45tgr"; System.out.println(str.compareTo(str2));//-3 java.util.Date d ; //根据日期的长整形数比较 } Comparator: 提供排序的比较器,业务比较器,实现java.util.Comparator接口,重写public int compare(T o1,T o2). public class Demo04 { /** * @param args */ public static void main(String[] args) { Date[] arr =new Date[3]; arr[0] =new Date(); arr[1] =new Date(System.currentTimeMillis()-1000*60*60); arr[2] =new Date(System.currentTimeMillis()+1000*60*60); Utils.sort(arr); //降序 System.out.println(Arrays.toString(arr)); //字符串 String[] arr2 ={"a","abcd","abc","def"}; Utils.sort(arr2); System.out.println(Arrays.toString(arr2)); System.out.println("==========List排序==========="); //存放容器中 List<String> list =new ArrayList<String>(); list.add("a"); list.add("abcd"); list.add("abc"); list.add("def"); Utils.sort(list); System.out.println(list); System.out.println("==========使用Comparator 排序数组==============="); arr2 =new String[]{"a","abcd","abc","def"}; Utils.sort(arr2,new StringComp()); System.out.println(Arrays.toString(arr2)); System.out.println("==========List排序+比较器==========="); list =new ArrayList<String>(); list.add("a"); list.add("abcd"); list.add("abc"); list.add("def"); Utils.sort(list,new StringComp()); System.out.println(list); } } /** * 排序 * @author Administrator * */ public class Utils { /** * List的排序+比较器 * @param list * @param com */ public static <T> void sort(List<T> list,Comparator<T> com){ //第一步:转成数组 Object[] arr =list.toArray(); sort(arr,com); //第二步:改变容器中对应的值 for(int i=0;i<arr.length;i++){ list.set(i, (T)(arr[i])); } } /** * 数组的排序 (降序)+Comparator接口 * @param arr */ public static <T> void sort(Object[] arr,Comparator<T> com){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(com.compare((T)arr[i], (T)arr[i+1])<0){ Object temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } /** * 容器排序 (使用泛型方法) */ public static <T extends Comparable<T>> void sort(List<T> list){ //第一步:转成数组 Object[] arr =list.toArray(); sort(arr); //第二步:改变容器中对应的值 for(int i=0;i<arr.length;i++){ list.set(i, (T)(arr[i])); } } /** * 数组排序 (使用泛型方法) */ public static <T extends Comparable<T>> void sort(T[] arr){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(((Comparable)arr[i]).compareTo(arr[i+1])<0){ T temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } /** * 数组的排序 (降序) * @param arr */ public static void sort(Object[] arr){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(((Comparable)arr[i]).compareTo(arr[i+1])<0){ Object temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } } public class StringComp implements java.util.Comparator<String>{ /** * 按长度比较大小 * 正数 > * 负数 < * 0 == */ @Override public int compare(String o1, String o2) { int len1 =o1.length(); int len2 =o2.length(); return -(len1-len2); } } /** * 使用Collections对容器的比较 * 1、 public static <T> void sort(List<T> list, Comparator<? super T> c) * 2、public static <T extends Comparable<? super T>> void sort(List<T> list) * void sort(List<T> list) * @author Administrator * */ public class Demo05 { /** * @param args */ public static void main(String[] args) { List<String> list =new ArrayList<String>(); list.add("a"); list.add("abcd"); list.add("abc"); list.add("def"); Collections.sort(list,new StringComp()); System.out.println(list); list =new ArrayList<String>(); list.add("a"); list.add("abcd"); list.add("abc"); list.add("def"); Collections.sort(list); System.out.println(list); } } 内置引用数据类型的排序: 1实现Comparable接口,重写compareTo方法, 2实现Comparator接口,重写compare方法, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.pubTime) 自定义类型也是这样。 import java.text.SimpleDateFormat; import java.util.Date; /*public interface Comparable<T> { public int compareTo(T o); }*/ public class NewsItem implements java.lang.Comparable<NewsItem>{//实现Comparable接口,重写compareTo方法。 //标题 private String title; //点击量 private int hits; //时间 private Date pubTime; public NewsItem() { } public NewsItem(String title, int hits, Date pubTime) { super(); this.title = title; this.hits = hits; this.pubTime = pubTime; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getHits() { return hits; } public void setHits(int hits) { this.hits = hits; } public Date getPubTime() { return pubTime; } public void setPubTime(Date pubTime) { this.pubTime = pubTime; } //时间降序 +点击量升序+标题降序 @Override public int compareTo(NewsItem o) {//重写compareTo方法 int result =0; /*比较 时间,降序,直接比较,Date实现了Comparable<Date>接口,重写了compareTo方法, public int compareTo(Date anotherDate) { long thisTime = getMillisOf(this); long anotherTime = getMillisOf(anotherDate); return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1)); }*/ result =-this.pubTime.compareTo(o.pubTime); if(0==result){ //时间相同 //点击量 result =this.hits-o.hits; //升序 if(0==result){ //点击量相同 //标题 result=-this.title.compareTo(o.title);//降序,String继承了Comparable<String>接口,重写了compareTo方法。 } } return result; } @Override public String toString() { StringBuilder sb =new StringBuilder(); sb.append("标题:").append(this.title); sb.append(",时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.pubTime)); sb.append(",点击量:").append(this.hits).append("\n"); return sb.toString(); } } public class NewsItemApp { public static void main(String[] args) { List<NewsItem> news=new ArrayList<NewsItem>(); news.add(new NewsItem("美国后怕了,逃跑了悲剧了",50,new Date(System.currentTimeMillis()-1000*60*60))); news.add(new NewsItem("中国登上钓鱼岛了,全国欢呼了",100,new Date())); news.add(new NewsItem("小日本终于听话了,泪流满面笑了",60,new Date(System.currentTimeMillis()-1000*60*60))); System.out.println("排序前:"+news); //排序 Collections.sort(news); /* public static <T extends Comparable<? super T>> void sort(List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } } //上述方法的解释: ListIterator<E> listIterator(); public interface ListIterator<E> extends Iterator<E> {} public interface Iterator<E> {} public static <T> void sort(List<T> list, Comparator<? super T> c) { Object[] a = list.toArray(); Arrays.sort(a, (Comparator)c); ListIterator i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set(a[j]); } }*/ Utils.sort(news); /** 容器排序 (使用泛型方法) public static <T extends Comparable<T>> void sort(List<T> list){ //第一步:转成数组 Object[] arr =list.toArray(); sort(arr); //第二步:改变容器中对应的值 for(int i=0;i<arr.length;i++){ list.set(i, (T)(arr[i])); } } 数组的排序 (降序) public static void sort(Object[] arr){ //从大到小排序 降序 boolean sorted= true; int len =arr.length; for(int j=0;j<len-1;j++){ //趟数 sorted =true; //假定有序 for(int i=0;i<len-1-j;i++){ //次数 if(((Comparable)arr[i]).compareTo(arr[i+1])<0){ Object temp = arr[i]; arr[i] =arr[i+1]; arr[i+1] =temp; sorted =false; //假定失败 } } if(sorted){ //减少趟数 break; } } } */ System.out.println("排序后"+news); } } 另外一种排序方式: 实体类不进行排序,由另外一个类提供排序的方法。 /** * 实体类 * @author Administrator * */ public class Goods {//不实现任何接口 //商品名称 private String name; //价格 private double price; //收藏量 private int fav; public Goods() { // TODO Auto-generated constructor stub } public Goods(String name, double price, int fav) { super(); this.name = name; this.price = price; this.fav = fav; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getFav() { return fav; } public void setFav(int fav) { this.fav = fav; } @Override public String toString() { return "商品名:"+name+",收藏量"+this.fav+",价格:"+this.price+"\n"; } } /** * 按价格排序的业务类 (降序) * @author Administrator * */ public class GoodsPriceComp implements java.util.Comparator<Goods> {//public interface Comparator<T> {}实现的时候就可以传类型进来。 @Override public int compare(Goods o1, Goods o2) { return -(o1.getPrice()-o2.getPrice()>0?1:(o1.getPrice()==o2.getPrice()?0:-1)); } } public class GoodsApp { /** * @param args */ public static void main(String[] args) { List<Goods> list =new ArrayList<Goods>(); list.add(new Goods("老马视频",100,2000)); list.add(new Goods("老高视频",50,2000)); list.add(new Goods("老裴视频",1000,1000)); System.out.println("排序前:"+list); //按照不同的方式排序 Collections.sort(list,new GoodsPriceComp()); Collections.sort(list,new GoodsFavComp());//public class GoodsPriceComp implements Comparator<Goods> /* public static <T> void sort(List<T> list, Comparator<? super T> c) {// Object[] a = list.toArray(); Arrays.sort(a,(Comparator)c); // ListIterator<E> listIterator(); public interface ListIterator<E> extends Iterator<E> ListIterator i=list.listIterator(); for(int j=0;j<a.length;j++) { i.next(); i.set(a[j]); } } */ System.out.println("排序后:"+list); } } 之前用的排序,是把数据放在ArrayList容器中,ArrayList本身是不可以排序的,需要借助其他类进行排序。 但是TreeSet,TreeMap是可以排序的。 TreeSet是Set接口的一个实现类,Set是不可重复的,所以TreeSet也是不可重复的,并且可以排序。 Set接口的另一个实现类HashSet,HashSet里面的元素必须重写HashCode和equals方法。TreeSet不需要重写HashCode和equals方法。 排序:1、元素本身可以排序(类实现Comparable接口+重写compareTo方法).2提供额外排序类(类实现Comparator接口+重写compare方法)。 new TreeSet()实例化一个空构造TreeSet方法,然后往里面添加元素时这个元素必须可以排序(元素类实现Comparable接口+重写compareTo方法),如果元素不能排序则new TreeSet(Comparator<? super E> com),实例化TreeSet的时候要传一个Comparator子类对象进去,这个对象要实现Comparator接口并且重写compare方法用来排序。 使用额外排序类: public class Person { private final String name;//名称 private final int handsome;//帅气指数 public Person() {//final变量必须初始化值 name =null; handsome =0; } public Person(String name, int handsome) { super(); this.name = name; this.handsome = handsome; } public String getName() { return name; } public int getHandsome() { return handsome; } @Override public String toString() { return "姓名:"+this.name+",帅气指数:"+this.handsome+"\n"; } } /** * 提供了 解耦的方式:业务排序类 * @author Administrator * */ public class TreeSetDemo { /** * @param args */ public static void main(String[] args) { Person p1 =new Person("您",100); Person p2 =new Person("刘德华",1000); Person p3 =new Person("梁朝伟",1200); Person p4 =new Person("老裴",50); //依次存放到TreeSet容器中,使用排序的业务类(匿名内部类) /*public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<E,Object>(comparator)); }*/ TreeSet<Person> persons =new TreeSet<Person>( new java.util.Comparator<Person>(){ @Override public int compare(Person o1, Person o2) {// return (o1.getHandsome()-o2.getHandsome());//这是升序,加了负号后就是降序了, } } ); persons.add(p1); //TreeSet 在添加数据的过程中进行排序,添加p2的时候就会跟p1比较。添加p3的时候就会跟p2,p1比较。 persons.add(p2); persons.add(p3); persons.add(p4); System.out.println(persons); //TreeSet是在添加数据的时候排序,改变数据不会更改排序的结果。所以使用的时候不要修改数据,所以类的变量改为final类型,这样这个属性一当赋值就不能改变了。 p4.setHandsome(100);//错误,属性类型为final不能修改 p4.setName("您");//错误,属性类型为final不能修改 //p4 与p1 内容重复 System.out.println(persons); } } 实体类实现Comparable 接口的应用: public class Worker implements java.lang.Comparable<Worker> {//实现接口的时候就标明类型, //工种 private String type; //工资 private double salary; public Worker() { // TODO Auto-generated constructor stub } public Worker(String type, double salary) { super(); this.type = type; this.salary = salary; } public String getType() { return type; } public void setType(String type) { this.type = type; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } /** * 按工资升序 */ @Override public int compareTo(Worker o) {//升序,大于就排在后面 return this.salary>o.salary?1:( this.salary==o.salary?0:-1);//1、-1是随便的,只要是正数负数就可以。 } @Override public String toString() { return "工种:"+this.type+",工资:"+this.salary+"\n"; } } public class TreeSetDemo2 { /** * @param args */ public static void main(String[] args) { Worker w1 =new Worker("垃圾回收员",12000);//实体类实现Comparable接口 Worker w2 =new Worker("农民工",8000); Worker w3 =new Worker("程序猿",5000); TreeSet<Worker> employees =new TreeSet<Worker>(); employees.add(w1); employees.add(w2); employees.add(w3); System.out.println(employees); } } TreeMap: 确保key可以排序或者提供比较器,public TreeMap(Comparator<? super K> comparator), public class TreeMapDemo { public static void main(String[] args) { Person p1 =new Person("您",100); Person p2 =new Person("刘德华",1000); Person p3 =new Person("梁朝伟",1200); Person p4 =new Person("老裴",50); TreeMap<Person,String> map =new TreeMap<Person,String>(new java.util.Comparator<Person>(){ @Override public int compare(Person o1, Person o2) { return -(o1.getHandsome()-o2.getHandsome());//降序, } } ); map.put(p1, "bjsxt"); map.put(p2, "bjsxt"); map.put(p3, "bjsxt"); map.put(p4, "bjsxt"); //查看键 Set<Person> persons =map.keySet(); System.out.println(persons); } } public class TreeMapDemo02 { public static void main(String[] args) { Worker w1 =new Worker("垃圾回收员",12000); Worker w2 =new Worker("农民工",8000); Worker w3 =new Worker("程序猿",5000); TreeMap<Worker,String > employees =new TreeMap<Worker,String >(); employees.put(w1,"bjsxt"); employees.put(w2,"bjsxt"); employees.put(w3,"bjsxt"); System.out.println(employees.keySet()); } } Collections是一个类,Collection是一个接口。 /** *1、 binarySearch(List<? extends Comparable<? super T>> list, T key) //2分法查找,需要容器List有序, *2、排序方法:sort(List<T> list) sort(List<T> list, Comparator<? super T> c) *3、容器元素反转:reverse(List<?> list) 4、打乱顺序:shuffle(List<?> list) 洗牌 5、交换数据:swap(List<?> list, int i, int j) */ public class CollectionsDemo01 { /** * @param args */ public static void main(String[] args) { List<Integer> cards =new ArrayList<Integer>(); //shuffle 洗牌,模拟斗地主,斗地主一共54张牌, for(int i=0;i<54;i++){ cards.add(i); } Collection c; //洗牌,打乱顺序, Collections.shuffle(cards) ; //依次发牌,每人27张牌。 List<Integer> p1 =new ArrayList<Integer>(); List<Integer> p2 =new ArrayList<Integer>(); List<Integer> p3 =new ArrayList<Integer>(); List<Integer> last =new ArrayList<Integer>(); for(int i=0;i<51;i+=3){//i每次加3 p1.add(cards.get(i)); p2.add(cards.get(i+1)); p3.add(cards.get(i+2)); } //最后三张为底牌 last.add(cards.get(51)); last.add(cards.get(52)); last.add(cards.get(53)); System.out.println("第一个人:"+p1); System.out.println("第二个人:"+p2); System.out.println("第三个人:"+p3); System.out.println("底牌为:"+last); } //反转 public static void test1(){ List<Integer> list =new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); list.add(4); System.out.println(list); Collections.reverse(list);//元素反转, System.out.println("反转之后"+list); } }