黑马程序员_java集合(2) 泛型&数组与集合工具类

时间:2022-09-03 15:11:14
------- android培训java培训、期待与您交流! ----------

一.泛型

JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制

好处

1.将运行时期出现问题ClassCastException,转移到了编译时期。,

方便于程序员解决问题。让运行时问题减少,安全。,

 

2,避免了强制转换麻烦。

泛型格式:通过<>来定义要操作的引用数据类型。

在使用java提供的对象时,什么时候写泛型呢?

通常在集合框架中很常见,

只要见到<>就要定义泛型。

其实<> 就是用来接收类型的。

当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可


eg:
import java.util.*;
class GenericDemo
{
public static void main(String[] args)
{
//使用泛型进行限定元素类型
ArrayList<String> al = new ArrayList<String>();

al.add("abc01");//被限定以后,只能添加与限定类型相同类型的元素
al.add("abc0991");
al.add("abc014");

//al.add(4);
////al.add(new Integer(4));//如果添加的元素类型不正确会编译失败


Iterator<String> it = al.iterator();
while(it.hasNext())
{
String s = it.next();

System.out.println(s+":"+s.length());
}
}
}

泛型类定义的泛型,在整个类中有效。如果被方法使用,

那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。

为了让不同方法可以操作不同类型,而且类型还不确定。

那么可以将泛型定义在方法上。 

特殊之处:

静态方法不可以访问类上定义的泛型。

如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上

eg:
//泛型定义到类上
class Demo<T>
{
public void show(T t)
{
System.out.println("show:"+t);
}
public void print(T t)
{
System.out.println("show:"+t);
}

}
class Demo<T>
{
//泛型定义到方法上,使用本类的泛型进行定义
public void show(T t)
{
System.out.println("show:"+t);
}
//将泛型定义到方法上,可以使用与本类不同的泛型定义
public <Q> void print(Q q)
{
System.out.println("print:"+q);
}
//静态方法不能使用类上定义的泛型,静态方法必须把泛型定义到方法上。
public static <W> void method(W t)
{
System.out.println("method:"+t);
}
}
class GenericDemo4
{
public static void main(String[] args)
{
Demo <String> d = new Demo<String>();
d.show("haha");
//d.show(4);//使用与泛型类不同类型的参数传递给泛型方法会编译失败
d.print(5);
d.print("hehe");

Demo.method("hahahahha");


}
}

eg2:
//泛型定义在接口上。
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 GenericDemo5
{
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的父类型。下限


eg:
import java.util.*;
class GenericDemo6
{
public static void main(String[] args)
{


ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("abc1"));
al.add(new Person("abc2"));
al.add(new Person("abc3"));
//printColl(al);

ArrayList<Student> al1 = new ArrayList<Student>();
al1.add(new Student("abc--1"));
al1.add(new Student("abc--2"));
al1.add(new Student("abc--3"));
printColl(al1);

}
//使用泛型限定方式,参数意为任意继承自Person的类型
public static void printColl(Collection<? extends Person> al)
{
Iterator<? extends Person> it = al.iterator();
while(it.hasNext())
{
System.out.println(it.next().getName());
}
}

public static void printColl(ArrayList<?> al)//ArrayList al = new ArrayList<Integer>();error
{
Iterator<?> it = al.iterator();


while(it.hasNext())
{
System.out.println(it.next().toString());
}
}

}

class Person
{
private String name;
Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
//写一个类继承Person类
class Student extends Person
{
Student(String name)
{
super(name);
}
}

-------------------------------------------------------------------------------------------------------------------------------

二.Arrays工具类

里面都是静态方法

asList:将数组变成list集合

1.把数组变成list集合有什么好处?

可以使用集合的思想和方法来操作数组中的元素。 

注意:

1.将数组变成集合,不可以使用集合的增删方法。

因为数组的长度是固定。只可以使用一下等不涉及增删的方法。

contains。

get

indexOf()

subList();

 

如果你增删。那么会反生UnsupportedOperationException,

 

如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。

如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在


eg:
import java.util.*;
class ArraysDemo
{
public static void main(String[] args)
{

String[] arr = {"abc","cc","kkkk"};

List<String> list = Arrays.asList(arr);
sop("contains:"+list.contains("cc"));//集合中判断是否包含某个元素。
//list.add("qq");//向转换后的集合中添加元素会出现UnsupportedOperationException,

sop(list);

//int[] num1 = {2,4,5};
//List<int[]> li = Arrays.asList(nums);会将该数组作为集合中的元素存在。

Integer[] nums = {2,4,5};//将数组中元素作为集合中元素存在。
List<Integer> li = Arrays.asList(nums);

sop(li);
}
//如果想要知道数组中是否包含一个元素,需要将数组遍历逐个比较,较为麻烦,
//将数组转换为集合,可以使用集合中的操作方法,较为方便。
public static boolean myContains(String[] arr,String key)
{
for(int x=0;x<arr.length; x++)
{
if(arr[x].equals(key))
return true;
}
return false;
}

public static void sop(Object obj)
{
System.out.println(obj);
}

}


-------------------------------------------------------------------------------------------------------------------------------

三.Collections工具类

Collections:集合框架的工具类。里面定义的都是静态方法。

Collections和Collection有什么区别?

Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。

它有两个常用的子接口,

List:对元素都有定义索引。有序的。可以重复元素。

Set:不可以重复元素。无序。

Collections是集合框架中的一个工具类。该类中的方法都是静态的

提供的方法中有可以对list集合进行排序,二分查找等方法。

通常常用的集合都是线程不安全的。因为要提高效率。

如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的

eg:

import java.util.*;
class CollectionsDemo
{
public static void main(String[] args)
{
sortDemo();

}
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");//使用二分搜索法搜索指定列表,以获得指定对象。

sop("index="+index);
}
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);
// 根据元素的自然顺序,返回给定 collection 的最大元素。也可以使用自己指定的比较器。
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);// 根据元素的自然顺序 对指定列表按升序进行排序。
//使用自己指定的比较器对集合进行排序。
Collections.sort(list,new StrLenComparator());
//Collections.swap(list,1,2);//交换集合中两个元素的位置。
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);
}
}
import java.util.*;//按照与自然顺序相反的顺序进行比较。reseveOrder方法底层实现原理。class StrComparator implements Comparator<String>{public int compare(String s1,String s2){return s2.compareTo(s1);}}//按照字符串的长度进行比较。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);}}class CollectionsDemo2 {public static void main(String[] args) {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(){//对不具备比较性的元素或者不是需求比较方法的元素可以指定一个比较器对集合中元素进行比较。//使用reveseOrder方法进行反转以后得到一个反转比较方法后的比较器,作为参数传递进去。TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));//Collections.reverseOrder()可以返回一个与自然顺序相反的比较器。//TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());ts.add("abcde");ts.add("aaa");ts.add("k");ts.add("cc");Iterator it = ts.iterator();while(it.hasNext()){System.out.println(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);}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);}public static void sop(Object obj){System.out.println(obj);}}

集合变数组。

Collection接口中的toArray方法。

<T> T[]  toArray(T[] a) 

 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 

 

1,指定类型的数组到底要定义多长呢?

当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。

当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。

所以创建一个刚刚好的数组最优。

 

2,为什么要将集合变数组?

为了限定对元素的操作。不需要进行增删了

eg:

import java.util.*;
class CollectionToArray
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();

al.add("abc1");
al.add("abc2");
al.add("abc3");
//将集合中的元素存入数组中去。
String[] arr = al.toArray(new String[al.size()]);
System.out.println(Arrays.toString(arr));
}
}




------- android培训java培训、期待与您交流! ----------