黑马程序员_Java基础_集合框架工具类
来源:互联网 发布:mac book air后悔 编辑:程序博客网 时间:2024/04/25 01:46
首先要明确Collections和Collection是两个完全不同的概念,Collection是集合框架中的一员,它是一个根接口,他有很多子接口,其中有我们最常用的List和Set集合。Collections是集合框架的工具类,它有很多方法可以对很多集合进行操作,并且它没有构造函数,它提供的方法都是静态的,因为它能操作的集合都共享它的方法,所以将这些方法定义成静态的。
举个最简单的例子,当我们想要使用一个集合,不许要保证里面的元素唯一,所以我们只可以使用List集合,我们要对List集合排序,但是List集合没有排序功能,所以既可以使用集合框架工具类的Collections的Sort()方法,对List集合进行排序。这就是Collections的强大之处。
1,sor有两个方法:
public static <T extends Comparable<? super T>> void sort(List<T> list)
<T extends Comparable<? super T>>的含义是:List集合里面存储的元素是未知类型,我们将这个未知类型假设为T类型,也就是泛型,使用该Sort方法,T类型需要实现Comparable接口,而Comparable接口也要定义成泛型,它操作的类型是T类型,但是为了提高它的扩展性,所以允许Comparable接口的泛型定义成T或者其父类型。
public static <T> void sort(List<T> list,Comparator<? super T> c)
第二各参数传入的是自定义的比较器,对于没有比较性的对象,必须建立自己的比较器。
注意:Collections类的Sort方法是不能操作Set集合的,原因是Set集合有TreeSet子类,具有排序的方法。
2,max()的两个方法:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
该方法使用来获取集合中排序后的末尾的那个元素,比如:List集合中存入字符串,使用默认的比较器,该方法会返回List集合里面的字符串按自然顺序排序后的最后一个字符串。
Collection<? extends T> coll的含义是:集合的泛型类型是T或者T的子类型。
<T extends Object & Comparable<? super T>>的含义是:T必须是Object类的子类,并且T要实现Comparable接口,Comparable接口的泛型是T或者T的父类型。
需求:自定义一个List集合,里面存储不同的字符串,调用sort和max方法,使用默认的比较器输出List集合中字符串结果,然后自定义一个比较器,比较字符串长度,在调用sort和max方法传入自定义比较器,输出结果。
import java.util.*;public class CollectionsDemo1{ public static void main(String[] args) { ArrayList<String> al = new ArrayList<>(); al.add("sda"); al.add("ss"); al.add("dd"); al.add("klsfj"); System.out.println(al); //字符串是具有比较性的,所以sort方法采用的是字符串自然排序 Collections.sort(al); //打印字符串的自然顺序的排序结果 System.out.println(al); System.out.println(Collections.max(al)); //返回自然派序的最后一个 //使用自定义比较器,对List集合进行排序,该比较器比较的是字符串长度。 Collections.sort(al,new myComp()); System.out.println(al); System.out.println(Collections.max(al,new myComp()));//返回最大长度 }}//定义比较字符串长度的比较器class myComp 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); }}
3,binarySearch()的两个方法:
二分查找的前提是集合的元素必须要有序。
public static <T> int binarySearch(List<? extends Comparable<? super T>> list,
T key)
该方法是按照默认的比较器,也就是自然顺序对List集合中的元素进行二分查找。比如字符串,会按照字典顺序查找所需要的元素的角标。
public static <T> int binarySearch(List<? extends T> list,
T key,
Comparator<? super T> c)
该方法按照自定义的比较器对集合的元素进行查找。
没有比较器的二分查找的原理代码:
public static <T> int myBinarySearch(List<? extends Comparable<? super T>> list,T key) { int min = 0; int max = list.size() - 1; int mid = 0; while(min<max) { mid = (min + max)>>1; 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 -num-1;//这是Collections集合的默认原理,当找不到元素所在位置时,将该元素应该所在的位置-1}
有自定义比较器的二分查找原理:
public static <T> int myBinarySearch(List<? extnds Comparable<? super T>> list,T key,Comparator<? super T> c) { int min = 0 ; int max = list.size()-1; int mid = 0; while(min < max) { mid = (min + max)>>1; String str = list.get(mid); int num = c.compare(str,key); if(num>0) max = mid - 1; else if(num<0) min = mid + 1; else return mid; } return -min-1;}
需求:同样是对List集合的String类型的字符串元素进行操作,按照字符串长度,使用binarySearch(),进行二分查找。
import java.util.*;public class CollectionsDemo2{ public static void main(String[] args) { ArrayList<String> al = new ArrayList<>(); al.add("sda"); al.add("ss"); al.add("dd"); al.add("klsfj"); //首先集合里面的的元素必须是有顺序的 Collections.sort(al,new myComp()); System.out.println(al); //使用自定义比较器,按照字符串长度查找 int n = Collections.binarySearch(al,"sss",new myComp()); //如果二分查找没有索要查找元素,则返回的是:-(该插入位置)-1 System.out.println(n); }}//自定义比较器,按照字符串长度比较class myComp 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); }}
4,public static <T> void fill(List<? super T> list,T obj)
使用指定元素替换指定列表中的所有元素。
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)
将List集合中的旧值替换成成指定的新值。
public static void reverse(List<?> list)
将集合中的元素顺序反转。
import java.util.*;public class CollectionTest{ public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("na"); list.add("bbb"); list.add("sdg"); list.add("dg"); System.out.println(list); //将List集合中的所有元素替换成yyy //Collections.fill(list,"yyy"); //System.out.println(list); //替换List集合中的一部分元素,替换角标为1——2的元素为yyy tihuan(list,1,3); //反转替换后的集合元素顺序 Collections.reverse(list); System.out.println(list); }//替换过程代码 public static void tihuan(List<String> list,int s,int e) { for(int i=s;i<e;i++) { list.remove(i); list.add(i,"yyy"); } System.out.println(list); }}
二,Collections的reverseOrder()方法:
reverseOrder方法是Collections集合工具类的一个重要方法,所以单独拿出来总结。
public static <T> Comparator<T> reverseOrder()
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
该方法返回一个Comparator比较器,但是该比较器是默认比较器的逆向比较方法。
比如说字符串的默认比较方式是自然顺序,该顺序是通过实现Comparable接口,重写它的compareTo方法,来按照自然顺序比较字符串。当我们将字符串作为元素存储到List集合中时,通过Collections类的sort()方法对字符串排序,那么结果将会是自然顺序排序后的字符串,如果我们将Collections.reverseOrder()作为一个参数传递给sort方法,那么结果将和自然顺序相反。该方法是可以应用到TreeSet集合的,因为TreeSet集合允许接收一个比较器。
请看谢列需求:
需求:将不同长度的字符串作为元素传递给TreeSet集合,按照字符串的长短输出结果,反别输出字符串从长到短和从短到长的两种不同的结果。
按照以前的思维我们通常是定义两个比较器,按别通过返回不同的值,来确定字符串的长短,但是学习了Collections的reverseOrder()方法后,我们可以直接返回一个与原比较器相反的比较器来进行操作。
import java.util.*;public class CollectionsDemo3{ public static void main(String[] args) { /* ArrayList<> list = new ArrayList<>(); list.add("shgsj"); list.add("asg"); list.add("dsh"); System.out.println("原List集合:" + list); Collections.sort(list); System.out.println("自然排序的结果:" + list); Collections.sort(list,Collections.reverseOrder()); System.out.println("自然顺序的逆序:" + list); */ //创建一个TreeSet集合,将自定义比较器的反向比较器传递给Set集合 TreeSet<String> ts = new TreeSet<>(Collections.reverseOrder(new myC())); //TreeSet<String> ts = new TreeSet<>(Collections.reverseOrder()); ts.add("fssssgdsf"); ts.add("sfsf"); ts.add("sgrrf"); ts.add("sdf"); sop(ts); iter(ts); //按照长度然后进行逆序排序; } //对集合中的元素进行迭代输出 public static void iter(TreeSet<String> ts) { Iterator<String> it = ts.iterator(); while (it.hasNext()) { sop(it.next()); } } public static void sop(Object obj) { System.out.println(obj); }}//定义一个比较器,按照字符串长度比较class myC 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); }}
三,之前我们说过Collection中的ArrayList集合几乎替代了Vector,ArrayList和Vector集合的用法是一模一样的,虽然Vector集合比ArrayList集合多了线程同步功能,但是因为它的效率低所以即使在多线程中,我们依然还是用ArrayList,然后自己加锁,其实集合框架工具类已经为我们提供了给List集合加锁的方法,我们只需要给该方法传入一个线程不同步的集合,他就能返回给我们一个线程同步的集合。
这些方法是:
public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T> List<T> synchronizedList(List<T> list)
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
public static <T> Set<T> synchronizedSet(Set<T> s)
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
四,数组工具类Arrays:
Arrays类和集合框架工具类Collections一样,提供了很多直接操作数组的静态法方发,很多静态方法我们之前已经使用过。
数组和List集合之间是可以相互转换的,转换方法就是Arrays提供的asList()静态方法。
但是将数组转换成集合要注意一下几个问题:
1,数组转换成集合后,不可以对该集合进行增删操作,因为数组的长度是固定不变的,但是可以进行查询操作,包括contains,indexOf,get,subList等操作;
2,如果数组是基本类型的数组,那么转换成集合后,集合的元素不是数组中的所有元素,而是这个数组对象。如果我们打印基本数据类型数组转换成集合后的结果,将看到的是一个地址值,也就是说转换后的集合只有一个元素。下面我们将通过一个程序进行验证。import java.util.*;public class ArraysDemo{ public static void main(String[] args) { //返回chs数组的字符串表示形式。没学该方法之前我们只能使用StringBuild进行这样的操作。 /*char[] chs = {'a','d','g','r'}; String s = Arrays.toString(chs);//静态方法引用一定不能忘了类 sop(s);//输出:[a,d,g,r] */ int[] i = {1,3,6,2,1};//如果将基本数据类型数组转换成集合那么,集合中的元素将是这个数组,而不是数组的元素 List<int[]> list = Arrays.asList(i); sop(list);//打印结果是:[[I@10be6858] Integer[] li = {1,2,4,6,7}; //引用了数据类型的拆箱和装箱,数组中存储的元素是对象 List<Integer> list2 = Arrays.asList(li); sop(list2); //list2.add(new Integer(6));//会抛出UnsupportedOperationException。 sop(list2.contains("6")); } public static void sop(Object obj) { System.out.println(obj); }}
3,既然数组可以转换成集合,那么集合也一定可以转换成数组,集合转换成数组是使用Collection集合框架中的toArray()方法。
这个方法有两种形式:
Object[] toArray()
<T> T[] toArray(T[] a)
前一个是返回Object类型的数组,后一个是返回泛型类型的数组。
(1)为什么要将集合变成数组呢?为了限制对集合中元素的操作,不需要进行增删操作了,可以将集合变成数组,别的用户就不能进行增删操作了。
当将集合转成数组的时候,如果指定的数组的长度小于等于集合的size,则会生成集合size大小的数组,当指定数组的长度大于集合的size的时候,会生成指定大小的数组,这个大小比集合的size大多少,就对应生成多少个null值放入数组的空位;所以,指定数组的大小最好是集合的size的大小;
import java.util.*;public class CollectionArrays{ public static void main(String[] args) { ArrayList<String> al = new ArrayList<>(); al.add("dzsfg04"); al.add("dzsfg01"); al.add("dzsfg02"); al.add("dzsfg03"); //String[] st = al.toArray(new String[0]); String[] st = al.toArray(new String[al.size()]); System.out.println(Arrays.toString(st)); } public static void sop(Object obj) { System.out.println(obj); }}
五,总结jdk1.5的几个新特性;
我们知道jdk1.5可以说是java发展的一个重大转折点,因为在这个版本增加了很多革命性的功能,所以这是很重要的一个知识点。面试可能会被问到。
1,泛型
2,增强for循环
3,可变参数
4,静态导入
5,自动装箱和拆箱
6,枚举
7,元数据
泛型我们已经学习过,增强for循环也已经在java基础知识里面总结过,在这里在比较一下增强for循环和普通for有什么区别:高级for必须要有被遍历的目标;比如打印100次hello world,高级for不能完成,传统for却可以。所以建议对数组进行遍历的时候采用传统的for循环,但是集合框架的遍历,高级for也可以使用。
增强的for循环:
语法:
for(数据类型 变量名 :被遍历的集合(Collection)或者数组)
{
}
重点要掌握增强for循环对List集合和对Map集合的操作:
import java.util.*;public class EnhanceFor{ public static void main(String[] args) { ArrayList<String> al = new ArrayList<>(); al.add("sdfg"); al.add("sdfdf"); al.add("sdaafa"); //使用迭代器迭代List集合 Iterator<String> it = al.iterator(); while (it.hasNext()) { System.out.println(it.next()); } //使用增强for循环迭代List集合 for (String s: al ) { System.out.println(s); } //增强for循环对Map集合的迭代 TreeMap<Integer,String> tm = new TreeMap<>(); tm.put(1,"fasd"); tm.put(2,"hasd"); tm.put(3,"kasd"); //方法一:keySet() Set<Integer> st = tm.keySet(); for (Integer num: st) { System.out.println(num + "----" + tm.get(num)); } //方法二:entrySet() Set<Map.Entry<Integer,String>> en = tm.entrySet(); for(Map.Entry<Integer,String> me: en) { System.out.println(me.getKey() + "======" + me.getValue()); } }}
可变参数:在Arrays数组工具类中的asList(T... args)方法上,可以就看到它的参数就是一个可变参数的。可变参数其实就是数组的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可。其实底层是JVM将这些参数封装到了一个数组中。
public class Kebiancanshu{ public static void main(String[] args) { show("sagj",3,5); show("ds",1,3,5); show("sda");//可变参数为空,长度为0 public static void show(int i,int j) { System.out.println(i+j); } public static void show(int i,int j,int k) { System.out.println(i+k+j); } public static void show(String s,int... i) { System.out.println(i.length); }}
静态导入:导入的是所用静态类或对象中的静态成员。
特别注意:(1)当类名重名时,需要导入具体的包名;(2)当方法名重名是指定具体的类或者对象。
静态导入示例:
import static java.util.Arrays.*;//导入了java.util.Arrays的所有静态成员;public class StaticImportDemo{ public static void main(String[] args) { String[] arr = {"sg","sadg","stga"}; //Arrays.sort(arr); //可以省略Arrays sort(arr); System.out.println(Arrays.toString(arr));//为什么这个Arrays不可以删呢? //那是因为StaticImportDemo类是Object的子类,Object超类有自己的toString() //如果不加Arrays,它会认为引用的是超类的toString方法,会抛异常。 }}
- 黑马程序员_Java基础_集合框架工具类
- 黑马程序员_java基础_泛型、集合框架工具类
- 黑马程序员_Java基础_集合框架
- 黑马程序员_Java基础_集合框架
- 黑马程序员_java基础_集合框架
- 黑马程序员_Java基础_集合框架工具类相关应用
- 黑马程序员_Java基础_集合框架1
- 黑马程序员_Java基础_集合框架2
- 黑马程序员_Java基础_集合框架(一)_14
- 黑马程序员_Java基础_集合框架(二)_15
- 黑马程序员_Java基础_集合框架(三)_16
- 黑马程序员_Java基础_集合框架(四)_17
- 黑马程序员_Java基础04_集合框架
- 黑马程序员_Java基础_集合框架成员Collection
- 黑马程序员_Java基础_集合框架成员Map
- 黑马程序员_Java基础_集合框架1
- 黑马程序员_Java基础_集合框架2
- 黑马程序员_java基础学习笔记06_集合框架
- asp.NET配置
- 在堆中删除对象
- C#文档编辑器
- 【redis源码分析】字典---dict
- 访问堆中的数据成员
- 黑马程序员_Java基础_集合框架工具类
- Windows下获取Android系统源码
- POJ 2142 The Balance
- virt_to_phys virt_to_page page_to_virt phys_to_virt
- Debugging the kernel using Ftrace - part 1
- xen 前段后端
- c# 解析JSON的几种办法
- 学习笔记之 jsp基础 与 El表达式
- 学习使用easy-ui中combotree插件文档