-------android培训、java培训、期待与您交流! ----------
导读:Collection(sort,max,binarySearch,替换反转,SynList),Arrays,集合转化为数组,增强for循环,可变参数,静态导入
1、集合(Collection-sort,max,binarySearch)
- Collections做为一个工具类,它中的方法都是静态的。它没有构造函数是不需要创建对象的。因为它的对象中并没有去封装特有的数据。都是共享的情况下共享的最方便。我现在有一堆元素,我不需要保证唯一,要用List集合,可是我想对这里面的集合里进行排序,不能和Tree了,Tree是Set集合中的List集合中没有排序的方式,集合框架也想到了。它给你提供了工具来完成这样的动作。Collections这个对象,是专门用来对于集合进行操作的工具类。
- java.util 中Collections<Textends Comparable<? super T>>
void sort(List<T> list):根据元素的自然顺序 对指定列表按升序进行排序。
- List中的元素想要进行排序是不是都要进行比较,如果要是存入两个以上的学生的时候,比不了。因为学生本身不具有比较性。
- 集合框架的工具类。
- Collections:集合框架的工具类。里面定义的都是静态方法。
- Collections和Collection有什么区别?
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
Ø它有两个常用的子接口,
ØList:对元素都有定义索引。有序的。可以重复元素。
ØSet:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的
Ø 提供的方法中有可以对list集合进行排序,二分查找等方法。
Ø 通常常用的集合都是线程不安全的。因为要提高效率。
Ø 如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
- import java.util.*;
class CollectionsDemo
{
publicstatic void main(String[] args)
{
sortDemo();
}
//publicstatic <T> int binarySearch(List<? extends Comparable<? superT>> list,T key),如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。
publicstatic 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,newStrLenComparator());
sop(list);
//intindex = Collections.binarySearch(list,"aaaa");//将aaaa放在索引为1的位置上,才能保证还是有序的。结果为-2。即:-(1)-1
//intindex = halfSearch(list,"cc");
intindex = halfSearch2(list,"aaaa",new StrLenComparator());
sop("index="+index);
}
publicstatic int halfSearch(List<String> list,String key)
{
intmax,min,mid;
max= list.size()-1;
min= 0;
while(min<=max)
{
mid= (max+min)>>1;// /2;
Stringstr = list.get(mid);
intnum = str.compareTo(key);
if(num>0)
max= mid -1;
elseif(num<0)
min= mid + 1;
else
returnmid;
}
return-min-1;
}
publicstatic int halfSearch2(List<String> list,Stringkey,Comparator<String> cmp) //如果List中的元素没有比较性,用比较器。
{
intmax,min,mid;
max= list.size()-1;
min= 0;
while(min<=max)
{
mid= (max+min)>>1;// /2;
Stringstr = list.get(mid);
intnum = cmp.compare(str,key);
if(num>0)
max= mid -1;
elseif(num<0)
min= mid + 1;
else
returnmid;
}
return-min-1;
}
//publicstatic <T extends Object & Comparable<? super T>> Tmax(Collection<? extends T> coll)
publicstatic 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);
Stringmax = Collections.max(list/*,new StrLenComparator()*/);
sop("max="+max); //打印结果:max=zz
}
publicstatic 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); //它不能给Set排序,因为Set有TreeSet。publicstatic <T extends Comparable<? super T>> void sort(List<T>list)
Collections.sort(list,newStrLenComparator()); //如果不想用自然排序,可以传进来一个比较器。public static <T> voidsort(List<T> list,Comparator<? super T> c)
//Collections.swap(list,1,2); //交换第一个元素和第二个元素中的内容。
sop(list);
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
class StrLenComparator implementsComparator<String>
{
publicint compare(String s1,String s2) //对象比大小,不是compareTo()就是compare
{
if(s1.length()>s2.length())
return1;
if(s1.length()<s2.length())
return-1;
returns1.compareTo(s2);
}
}
/*
class Student
{
}
list.add(new Student());
//加泛型的目的就是为了编译的时候更安全,在编译时期做了限定。T可以任意,但是你必须具备比较性。因此T必须是Comparable的子类。一般Comparable和Comparator的后面都是super,因为接收的时候可以接收很多子类进来,用父类方法比。
public static <T extends Comparable<?super T>> void sort(List<T> list)
{
}
*/
2、集合(Collections-替换反转)
- 一定要想集合框架那个工具类有没有提供这个方法,如果没有我才干这件事,如果有,我打死都不干。static <T>Comparator<T>
- reverseOrder():返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。传进来一个逆项的比较器。reverseOrder返回的是一个比较器。
- import java.util.*;
class StrComparator implementsComparator<String>
{
publicint compare(String s1,String s2)
{
/*
intnum = s1.compareTo(s2); //s1和s2比较是正着的
if(num>0)
return-1;
if(num<0)
return1;
returnnum;
*/
returns2.compareTo(s1); //s2和要s1比是正着的。
}
}
class StrLenComparator implementsComparator<String>
{
publicint compare(String s1,String s2)
{
if(s1.length()>s2.length()) //按照长度排
return1;
if(s1.length()<s2.length())
return -1;
returns1.compareTo(s2); //长度按照相同的话,按照字母来排。
}
}
class CollectionsDemo2
{
publicstatic void main(String[] args)
{
shuffleDemo();
}
publicstatic 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);
}
publicstatic void orderDemo()
{
TreeSet<String>ts = new TreeSet<String>(Collections.reverseOrder(newStrLenComparator())); //static <T> Comparator<T> reverseOrder(Comparator<T>cmp):返回一个比较器,它强行逆转指定比较器的顺序。结果为:将长度的比较器输出的结果,逆转,即长度最长的在最上面,最短的在最下面。
ts.add("abcde");
ts.add("aaa");
ts.add("k");
ts.add("cc");
Iteratorit = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
publicstatic 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");
//List是按角标替换,replaceAll()可以按照内容替换。实际里面是按set(index,“pp”);封装,按角标找到元素后替换。static <T> Boolean replaceAll(List<T>list, T oldVal, T newVal):使用另一个值替换列表中出现的所有某一指定值。
sop(list);
Collections.reverse(list); //static void reverse(List<?> list):反转指定列表中元素的顺序。它实际用的是static void swap(List<?> list, int i,int j):在指定列表的指定位置处交换元素。
sop(list);
}
/*
练习。fill方法可以将list集合中所有元素替换成指定元素。
,将list集合中部分元素替换成指定元素。
*/
publicstatic 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。static <T> void fill(List<? superT> list, T obj):使用指定元素替换指定列表中的所有元素。
sop(list);
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
3、集合(Collections-SynList)(代码见上面)
- 集合中那么多的对象,它们都有一个共同的特点,那就是线程不安全。如是真的用到多线程的话,怎么办?自己加锁很麻烦,添加有一个方法,删除有一个方法,你是不是要把它的方法都添加到一个锁中去。在某一个时刻只能有一个线程进行添加或者删除动作。
- static <T> List<T> synchronizedList(List<T>list):返回指定列表支持的同步(线程安全的)列表。
static <K,V> Map<K,V> synchronizedMap(Map<K,V>m):返回由指定映射支持的同步(线程安全的)映射。
static <T> Set<T> synchronizedSet(Set<T>s):返回指定 set 支持的同步(线程安全的)set。
- 它们的底层是怎么实现的?
应用内部类,在添加,删除等方法的的前面加上了synchronized
4、集合(Arrays)
Ø binarySearch():二分法查找
Ø copyOf():数组复制
Ø copyOfRange:将数组中的指定范围复制到一个新的数组。
Ø equals():比较两个数组中的内容中否相同。
Ø deepEquals():不仅比较数组,还比较数组中元素的内容。
Ø fill():替换数组中的值。(可以替换数组中的一个范围)
Ø sort():排序。(还可以局部排序)
Ø toString():转化这字符串。
- Arrays:用于操作数组的工具类。[此类包含用来操作数组(比如排序和搜索)的各种方法]
- 里面都是静态方法。
- asList:将数组变成list集合
- import java.util.*;
class ArraysDemo
{
publicstatic void main(String[] args)
{
// int[]arr = {2,4,5};
// System.out.println(Arrays.toString(arr));
String[]arr = {"abc","cc","kkkk"};
/*
把数组变成list集合有什么好处?
可以使用集合的思想和方法来操作数组中的元素。(操作起来也比较方便)
注意:将数组变成集合,不可以使用集合的增删方法。
因为数组的长度是固定。
contains。
get
indexOf()
subList();
如果你增删。那么会反生UnsupportedOperationException,
*/
List<String>list = Arrays.asList(arr); //住这里面放字符串可以。//sop("contains:"+list.contains("cc"));
//list.add("qq");//UnsupportedOperationException,不能增删
//sop(list);
//int[]nums = {2,4,5};
Integer[]nums = {2,4,5};
List<Integer>li = Arrays.asList(nums); //这里要字为Integer数组做为集合中的元素存在。
/*
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。如,String[] arr ={"abc","cc","kkkk"}; abc,cc都作为集合中的元素存在。
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
*/
sop(li);
}
publicstatic boolean myContains(String[] arr,String key)
{
for(intx=0;x<arr.length; x++)
{
if(arr[x].equals(key))
returntrue;
}
returnfalse;
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
5、集合(集合转化为数组)
- 集合变数组:Collection接口中的toArray方法。
- Object[] toArray():返回包含此 collection 中所有元素的数组。
- <T> T[] toArray(T[] a):返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
- import java.util.*;
class CollectionToArray
{
publicstatic 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));
}
}
6、集合(增强for循环)
JDK1.5版本出现后的新特性:
- ArrayList取出数据的方式有两种,一种是是迭代,一种是for循环。Set集合只有一种取出方式,就是迭代器。
- Collection中定义了iterator():1.4版本是定义在它里面的1.5以后,给我它找了一个爹(publicinterface Collection<E>extends Iterable<E>),Iterable是从1.5后开始的一个接口,这个接口的出现实际上就是将迭代器,给抽取出来了。它还给我集合框架提供了一个新功能,那就是高级for循环:foreach循环。
- 高级for循环
格式:
for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) //没有Map,Map中不支持迭代。
{
}
- 对集合进行遍历。
只能获取集合元素。但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。
如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
- 传统for和高级for有什么区别呢?
高级for有一个局限性。必须有被遍历的目标。
- 建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
- import java.util.*;
class ForEachDemo
{
publicstatic void main(String[] args)
{
ArrayList<String>al = new ArrayList<String>();//在这里带着泛型,下面for就能用泛型的类型。
al.add("abc1");
al.add("abc2");
al.add("abc3");
for(Strings : al) //它在底层原理用的还是Iterator。封装了之后,把复杂的代码变成了简单的代码。这个升级是简化了书写。这个s的指向在做着变化。这个循环是有局限性的,它只能对集合中的元素进行取出,不能做修改动作。迭代器,至少能用一个remove(),如果你用的是列表迭代器的话,你还可以做增删改查。
{
//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,1};
for(intx=0; x<arr.length; x++)
{
System.out.println(arr[x]);
}
for(inti : arr)
{
System.out.println("i:"+i);
}
//凡是支持迭代器的集合,它们都支持高级for
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(Integeri : 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());
}
}
}
7、集合(可变参数)
JDK1.5版本出现的新特性。
- 方法的可变参数。在使用时注意:可变参数一定要定义在参数列表最后面。
class ParamMethodDemo
{
publicstatic void main(String[] args)
{
//show(3,4);
/*
//虽然少定义了多个方法。但是每次都要定义一个数组。作为实际参数。
int[]arr = {3,4};
show(arr);
int[]arr1 = {2,3,4,5};
show(arr1);
*/
/*
可变参数。
其实就是上一种数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。
*/
show("haha",2,3,4,5,6); //我们只要往里面传元素就行了,封装数组的动作不需要你来做,而是由虚拟机来帮你完成。数组不用new了,你爱传几个传几个。
//show(2,3,4,5,6,4,2,35,9);
//show();
}
publicstatic void show(String str,int... arr)//不要写[]了,还要接收一个数字进来。写三个点,叫可变参数。简化了代码,提高了开发的速度。Arr代表数组,先把前面的匹配完,剩下的都给我后面的了。
{
System.out.println(arr.length);
}
/*
publicstatic void show(int[] arr)
{
}
*/
/*
publicstatic void show(int a,int b)
{
System.out.println(a+","+b);
}
publicstatic void show(int a,int b,int c)
{}
*/
}
- static <T> List<T> asList(T...a):Arrays中的asList()方法,就是一个可变参数。
8、集合(静态导入)
- StaticImport 静态导入。
当类名重名时,需要指定具体的包名。(new packa.Demo();)
当方法重名是,指定具备所属的对象或者类。
- 如果没有静态的话导入的都是类。Import后写static的时候,你导入的都是某一个类的静态成员。
- import java.util.*;
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。
import static java.util.Collections.*;
/*
packa/Demo.class
packb/Demo.class
import packa.*;
import packb.*;
*/
import static java.lang.System.*;//导入了System类中所有静态成员。System中的都是静态的方法。
class StaticImport //extends Object,Object类先进来,接着导入的进来。
{
publicstatic void main(String[] args)
{
out.println("haha");
int[]arr = {3,1,5};
sort(arr); //Arrays中都是一个静态的方法,把Arrays这个类导进来的话,是不是不用写类名点了。
intindex = binarySearch(arr,1);
out.println(Arrays.toString(arr)); //虽然已经导入了Arrays,如果不写Arrays,就不知道是要用Object中的toString方法,还是Arrays中的toString()方法。
System.out.println("Index="+index);
ArrayListal = new ArrayList();
al.add(1);
al.add(3);
al.add(2);
out.println(al);
sort(al);
out.println(al);
}
}