Java集合框架(四)
Collections
集合框架的工具类
着重讲解以下方法:
1、sort():
1º根据元素的自然顺序对指定列表按升序进行排序,列表中的所有元素都必须实现comparable接口。
public static <T extends Comparable<? super T>> void sort(List<T> list)
2º根据指定比较器产生的顺序对指定列表进行排序。此列表内的所有元素都必须可使用指定比较器相互比较。
public static <T> void sort(List<T> list, Comparator<? super T> c)
2、max():
1º根据元素的自然顺序,返回给定collection的最大元素。collection中的所有元素都必须实现comparable接口。
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
2º根据指定比较器产生的顺序,返回给定collection的最大元素。collection中的所有元素都必须可通过指定比较器相互比较。
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)
3、binarySearch():
1º使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过sort(List)方法)。
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
2º使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据指定的比较器对列表进行升序排序(通过sort(List, Comparator) 方法)。
public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
示例代码演示上面方法:
/* 集合框架的工具类 Collections: */ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class CollectionsDemo { public static void main(String[] args) { //sortDemo(); //maxDemo(); binarySearchDemo(); } public static void binarySearchDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); list.add("qq"); list.add("z"); Collections.sort(list, new StrLenComparator());//指定比较器按字符串长度排序 sop(list); //int index = Collections.binarySearch(list, "aaaa"); //int index = halfSearch(list, "aaaa"); int index = halfSearch(list, "aaaa", new StrLenComparator()); sop("index = " + index); } /* * binarySearch()原理: * public static <T> int binarySearch * (List<? extends Comparable<? super T>> list, T key)原理: * */ public static int halfSearch(List<String> list, String key) { 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; } } //如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点 被定义为将键插入列表的那一点 return -min - 1; } /* * binarySearch()带比较器的原理: * public static <T> int binarySearch * (List<? extends T> list, T key, Comparator<? super T> c) */ public static int halfSearch(List<String> list, String key, Comparator<String> cmp) { int max, min, mid; max = list.size() - 1; min = 0; while(min <= max) { mid = (max + min) >> 1;// /2 String str = list.get(mid); //集合中的元素不具备比较性,或者具备的比较性不是我们所需要的,所以应该指定一个Comparator int num = cmp.compare(str, key);//此时不能调用compareTo()方法 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("kkkkk"); list.add("qq"); list.add("z"); Collections.sort(list); sop(list); String max = Collections.max(list, new StrLenComparator()); sop("max = " + max); } public static void sortDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); list.add("qq"); list.add("z"); sop(list); Collections.sort(list, new StrLenComparator()); sop(list); } public static void sop(Object obj) { System.out.println(obj); } } class StrLenComparator implements Comparator<String> { @Override public int compare(String s1, String s2) { int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if(num == 0) return s1.compareTo(s2); return num; } }
4、fill():
1º使用指定元素替换指定列表中的所有元素。
public static <T> void fill(List<? super T> list, T obj)
5、replaceAll():
1º使用另一个值替换列表中出现的所有某一指定值
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)
6、reverse():
1º反转指定列表中元素的顺序。
public static void reverse(List<?> list)
7、reverseOrder():
1º返回一个比较器,它强行逆转实现了Comparable接口的对象collection的自然顺序。
public static <T> Comparator<T> reverseOrder()
2º返回一个比较器,它强行逆转指定比较器的顺序。
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
8、shuffle():
1º使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。
public static void shuffle(List<?> list)
2º使用指定的随机源对指定列表进行置换。所有置换发生的可能性都是相等的,假定随机源是公平的。
public static void shuffle(List<?> list, Random rnd)
示例演示以上方法:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.TreeSet; class StrComparator implements Comparator<String> { @Override public int compare(String s1, String s2) { /* int num = s1.compareTo(s2); if(num > 0) return -1; if(num < 0) return 1; return num; */ return s2.compareTo(s1);//反转 } } class StringLenComparator implements Comparator<String> { @Override public int compare(String s1, String s2) { int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if(num == 0) return s1.compareTo(s2); return num; } } public class CollectionsDemo1 { public static void main(String[] args) { //fillDemo(); //replaceAllDemo(); /* List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); fillDemo(list, 1, 3, "liayun"); */ //orderDemo(); shuffleDemo(); } public static void shuffleDemo() { List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); list.add("qq"); list.add("z"); sop(list); Collections.shuffle(list);//使用默认随机源对指定列表进行置换 sop(list); } public static void orderDemo() { TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StringLenComparator())); ts.add("abcde"); ts.add("aaa"); ts.add("k"); ts.add("cc"); Iterator<String> it = ts.iterator(); while(it.hasNext()) { sop(it.next()); } } 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", "pp"); sop(list); Collections.reverse(list); sop(list); } /* fill()方法可以将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"); sop(list); } //练习:使用fill(),将list集合中部分元素替换成指定元素。 public static void fillDemo(List<String> list, int start, int end, String str) { for(int i = start; i < end; i++) { list.set(i, str); } sop(list); } public static void sop(Object obj) { System.out.println(obj); } }
Arrays
Arrays:用于操作数组的工具类。里面都是静态方法。
asList:将数组变成list集合。
问:把数组变成list集合有什么好处?
答:可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删方法(可以使用contains()/get()/indexOf()/subList()等)。 因为数组的长度是固定的。如果你增删,那么会生成UnsupportedOperationException。
- 如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。
- 如果数组中的元素都是基本数据类型,那么会将该数组(例:[[I@139a55])作为集合中的元素存在。
示例代码如下:
/* Arrays:用于操作数组的工具类。 里面都是静态方法。 asList:将数组变成list集合 */ import java.util.Arrays; import java.util.List; public class ArraysDemo { public static void main(String[] args) { //int[] arr = {2, 4, 5}; //System.out.println(Arrays.toString(arr)); String[] arr = {"abc", "cc", "kkk"}; //把数组变成list集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素 注意:将数组变成集合,不可以使用集合的增删方法。 因为数组的长度是固定的。 contains() get() indexOf() subList() 如果你增删,那么会生成UnsupportedOperationException。 */ List<String> list = Arrays.asList(arr); //System.out.println("contains:" + list.contains("cc")); //list.add("qq");//UnsupportedOperationException //System.out.println(list); int[] nums = {2, 4, 5}; //Integer[] nums = {2, 4, 5}; List<int[]> li = Arrays.asList(nums); /* 如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。 如果数组中的元素都是基本数据类型,那么会将该数组([[I@139a55])作为集合中的元素存在。 */ System.out.println(li); } }
集合变数组:Collections接口中的toArray()方法。
- 指定类型的数组到底要定义多长呢?当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。当指定类型的数组长度大于了集合的size,那么就不会新创建数组,而是使用传递进来的数组。所以创建一个刚刚好的数组最优。
- 为什么要将集合变数组?为了限定对元素的操作。不需要进行增删了。
示例代码如下:
/* 集合变数组。 Collections接口中的toArray()方法 */ import java.util.ArrayList; import java.util.Arrays; public class ArraysDemo1 { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc1"); al.add("abc2"); al.add("abc3"); /* 1、指定类型的数组到底要定义多长呢? 当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。 当指定类型的数组长度大于了集合的size,那么就不会新创建数组,而是使用传递进来的数组 所以创建一个刚刚好的数组最优 2、为什么要将集合变数组? 为了限定对元素的操作。不需要进行增删了。 */ String[] arr = al.toArray(new String[al.size()]); System.out.println(Arrays.toString(arr)); } }
高级for循环
格式:
for(数据类型(一般是泛型类型) 变量名 : 被遍历的集合(Collection)或者数组) { }
对集合进行遍历,只能获取集合中的元素,但是不能对集合进行操作。迭代器除了遍历,还可以进行remove()集合中元素的动作。如果使用ListIterator,还可以在遍历过程中进行对集合进行增删改查的操作。
问:传统for和高级for有什么区别呢?
答:高级for有一个局限性,必须有被遍历的目标。
建议:在遍历数组的时候还是希望使用传统for,因为传统for可以定义角标。
示例代码:
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class ForEachDemo { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc1"); al.add("abc2"); al.add("abc3"); for(String s : al) { s = "kk"; //System.out.println(s); } System.out.println(al); /* Iterator<String> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next()); } */ int[] arr = {3, 5, 6}; 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)); } //Set<Map.Entry<Integer, String>> entrySet = hm.entrySet(); //for(Map.Entry<Integer, String> me : entrySet) for(Map.Entry<Integer, String> me : hm.entrySet()) { System.out.println(me.getKey() + "---------" + me.getValue()); } } }
可变参数
JDK1.5版本出现的新特性。
可变参数:其实就是上一种数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。
方法的可变参数在使用时注意:可变参数一定要定义在参数列表的最后面。
示例代码:
public class ParamMethodDemo { public static void main(String[] args) { //show(3, 4); /* 虽然少定义了多个方法,但是每一次都要定义一个数组,作为实际参数。 int[] arr = {3, 4}; show(arr); int[] arr1 = {3, 4, 7, 5}; show(arr1); */ /* 可变参数 其实就是上一种数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可。 隐式将这些参数封装成了数组。 */ show("haha", 2, 3, 4, 5, 6); //show(2, 3, 4, 5, 6, 4, 2, 35, 9, "heiehi"); //show(); } public static void show(String str, int... arr) { System.out.println(arr.length); } /* public static void show(int[] arr) { } */ /* public static void show(int a, int b) { System.out.println(a + "," + b); } public static void show(int a, int b, int c) { } */ }
静态导入
StaticImport:静态导入。
注意:
- 当类名重名时,需要指定具体的包名。
- 当方法重名时,指定具备所属的对象或类。
示例代码如下:
import static java.util.Arrays.*;//导入的是Arrays类中的所有静态成员。 import java.util.Arrays; import static java.lang.System.*; //导入了System类中所有静态成员。 public class StaticImport { public static void main(String[] args) { out.println("haha"); int[] arr = {3, 1, 5}; sort(arr); int index = binarySearch(arr, 1); out.println("index = " + index); System.out.println(Arrays.toString(arr));//Arrays类中有toString(),Object类中也有toString(),不明确要使用哪个方法。 } }