Java集合--Map、Collections和Arrays

来源:互联网 发布:比较好的网络穿越小说 编辑:程序博客网 时间:2024/05/17 22:49

泛型

概述

JDK1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制。
优点:
1、将运行时期出现问题ClassCastException,转移到了编译时期。,方便于程序员解决问题。让运行时问题减少,安全。,
2、避免了强制转换麻烦。
格式:通过<>来定义要操作的引用数据类型。

在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型,<> 就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
import java.util.*;class GenericDemo{public static void main(String[] args) {ArrayList<String> al = new ArrayList<String>();al.add("java01");al.add("java09");al.add("java14");//al.add(4);  //往集合里面添加别的类型对象时,编译不通过Iterator<String> it = al.iterator();while(it.hasNext()){String s = it.next();  //避免了强制转换System.out.println(s+":"+s.length());}}}

泛型类

什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
Object:
class Tool {//定义Object,因为可以接受任何对象private Object obj; public void setObject(Object obj) {this.obj = obj;}public Object getObject() {return obj;}}
泛型类:
class Utils<QQ>{     //自定义一个泛型类private QQ q;public void setObject(QQ q){this.q = q;}public QQ getObject(){return q;}}class Worker{}class Student{}class  GenericDemo3{public static void main(String[] args) {Utils<Worker> u = new Utils<Worker>();u.setObject(new Student());  //这里如果传入的是学生对象的话那么编译不通过,因为已经限定了为工人类Worker w = u.getObject();;}}

泛型方法

当类型还不太确定的时候,将泛型定义在方法上,可以让不同方法可以操作不同类型
class Demo {public <T> 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 GenericDemo  {public static void main(String[] args)  {Demo d = new Demo();             //方法里面可以接受不同的 对象d.show("haha");  d.print(5);d.print("hehe");Demo.method("hahahahha");}}

泛型接口

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的父类型。下限
                         ? 通配符,也可以理解为占位符。
?extends E的体现:
import java.util.*;class Person {private String name;Person(String name) {this.name = name;}public String getName() {return name;}}class Student extends Person {Student(String name) {super(name);}}class  GenericDemo6 {public static void main(String[] args)  {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);  //ArrayList<? extends Person> al = new ArrayList<Student>();error}         //表示该方法能接受Person以及它的子类public static void printColl(Collection<? extends Person> al) { Iterator<? extends Person> it = al.iterator();while(it.hasNext()) {System.out.println(it.next().getName());}}}

?super E的体现:
import java.util.*;class TestWork {public static void main(String[] args) {//定义一个集合,只能 装Person对象TreeSet<Person> ts = new TreeSet<Person>(new Comp());ts.add(new Person("abc03"));ts.add(new Person("abc02"));ts.add(new Person("abc06"));ts.add(new Person("abc01"));Iterator<Person> it = ts.iterator();while(it.hasNext()) {System.out.println(it.next().getName());}TreeSet<Worker> ts1 = new TreeSet<Worker>(new Comp());ts1.add(new Worker("wabc--03"));ts1.add(new Worker("wabc--02"));ts1.add(new Worker("wabc--06"));ts1.add(new Worker("wabc--01"));Iterator<Worker> it1 = ts1.iterator();while(it1.hasNext()) {System.out.println(it1.next().getName());}}}/*class StuComp implements Comparator<Student>{public int compare(Student s1,Student s2){return s1.getName().compareTo(s2.getName());}}class WorkerComp implements Comparator<Worker>{public int compare(Worker s1,Worker s2){return s1.getName().compareTo(s2.getName());}}*/class Comp implements Comparator<Person> {  //Comparator接口的泛型就是?super E所以能接受Personpublic int compare(Person p1,Person p2) {return p2.getName().compareTo(p1.getName());}}//定义一个父类,以及继承它的两个子类class Person {private String name;Person(String name) {this.name = name;}public String getName() {return name;}public String toString() {return "person :"+name;}}class Student extends Person {Student(String name) {super(name);}}class Worker extends Person {Worker(String name) {super(name);}}

Map

特点

该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1、添加
put(K key, V value) 
putAll(Map<? extends K,? extends V> m)
2、删除
clear() 
remove(Object key)
3、判断
containsValue(Object value) 
containsKey(Object key) 
isEmpty()
4、获取
get(Object key) 
size() 
values()
                entrySet() 
keySet() 
Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
Set底层就是使用了Map集合。
import java.util.*;class Demo1Map {public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();//添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。并put方法会返回被覆盖的值。map.put("num1", "Jack");map.put("num2", "Moli");map.put("num3", "Paul");map.put("num4", "Luck");map.put("num5", "Paul");//sop(map.remove("num1"));  //根据键删除,键值对sop(map.containsValue("Paul"));  //map.containsKey("num1"),这两都是判断键值存不存在sop(map.get("num5"));  //根据键,获取值sop(map.size());  //获取集合长度Collection<String> co = map.values();sop(co);sop(map);}public static void sop(Object obj) {System.out.println(obj);}}

map集合的两种取出方式:

1、Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
import java.util.*;class Demo2Map {public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("num1", "Jack");map.put("num2", "Moli");map.put("num3", "Paul");map.put("num4", "Luck");Set<String> keyset = map.keySet(); //先获取map集合的所有键的Set集合,keySet();Iterator<String> it = keyset.iterator(); //有了Set集合。就可以获取其迭代器。while(it.hasNext()) {String key = it.next();String value = map.get(key);  //有了键可以通过map集合的get方法获取其对应的值。System.out.println(key+"="+value);}}}

2、Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
class Demo3Map {public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("num1", "Jack");map.put("num2", "Moli");map.put("num3", "Paul");map.put("num4", "Luck");Iterator<Map.Entry<String,String>> it = map.entrySet().iterator(); //使用entrySet方法,获取一个元素为Map.Entry类型的Set集合while(it.hasNext()) {Map.Entry<String, String> m = it.next();  System.out.println(m.getKey()+"="+m.getValue());  //使用Map.try接口里特有的方法获取}}}

Map扩展

Map集合被使用是因为具备映射关系
一个学校有多个教室,每一个教室都有名称。
import java.util.*;class Demo4Map {public static void main(String[] args) {Map<String,Map<String,String>> school = new HashMap<String,Map<String,String>> ();  //把Map集合定义的对象(班级)看成是一个元素,往学校里面存储Map<String,String> A = new HashMap<String,String> ();  //作为学校的班级,里面还存有学生Map<String,String> B = new HashMap<String,String> ();school.put("class1",A);  //往学校里面存储班级,以及名字school.put("class2",B);A.put("num1", "Jack");  //往班级里面再存储学生的编号和名字A.put("num2", "Moli");B.put("num1", "Paul");B.put("num2", "Luck");//遍历出班级Iterator<Map.Entry<String,Map<String,String>>> it = school.entrySet().iterator();while(it.hasNext()) {Map.Entry<String,Map<String,String>> m = it.next();Map<String,String> map = m.getValue();System.out.println(m.getKey());setStuInfo(map);}}//通过遍历出的班级定义一个获取学生的函数public static void setStuInfo(Map<String,String> map) {Iterator<String> it = map.keySet().iterator();while(it.hasNext()) {String s = it.next();System.out.println(map.get(s));}}}

Collections工具类

概述

Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection的区别
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口,List:对元素都有定义索引。有序的。可以重复元素。Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的提供的方法中有可以对list集合进行排序,二分查找等方法。通常常用的集合都是线程不安全的,因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

常用方法

sort():对list数组进行排序,该方法还可以传入一个比较器,自定义排序
max():根据元素的自然顺序,返回集合的最大值
reverse():反转
binarySearch():二分查找法(用于有序集合),如果查找的元素不存在,那么在返回在该元素(-插入点-1)。
fill():将指定元素全部替换到指定集合中去
replaceAll():将集合中指定元素,被新元素替换
reverseOrder():将集合中元素的排列顺序反转,里面可以传入比较器。
swap():直接置换集合中两个元素的位置
synchronizedList():将不同步的集合传入,是该集合同步
shuffle():把集合中的数据重新按照随机的顺序排放
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"); //二分查找法,元素必须是有序的//int index = halfSearch(list,"cc");int index = halfSearch2(list,"aaaa",new StrLenComparator());sop("index="+index);}//二分查找法的原理public static int halfSearch(List<String> list,String key){//定义三个变量取中间值,通过while循环,来判断元素的位置int max,min,mid;max = list.size()-1;min = 0;while(min<=max){mid = (max+min)>>1;//  (max+min)/2;String str = list.get(mid);int num = str.compareTo(key);if(num>0)max = mid -1;else if(num<0)min = mid + 1;elsereturn mid;}return -min-1;}//自定义排序的二分查找public static int halfSearch2(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);int num = cmp.compare(str,key);if(num>0)max = mid -1;else if(num<0)min = mid + 1;elsereturn 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);//根据元素的自然顺序,返回集合的最大值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 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 StrLenComparator()));  //将元素的排列顺序进行反转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 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);}}</string></string></string></string>

Array工具类

常用方法

用于操作数组的工具类,里面都是静态方法。
toString():将数组转换成字符串
asList:将数组变成list集合。优点:可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定。如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
import java.util.*;class  ArraysDemo{public static void main(String[] args) {//int[] arr = {2,4,5};//System.out.println(Arrays.toString(arr));  //将数组转换成字符串String[] arr = {"abc","cc","kkkk"};List<String> list = Arrays.asList(arr);  //数组转换成list集合//sop("contains:"+list.contains("cc"));//list.add("qq");//如果往转后后的集合里面使用增删方法,报UnsupportedOperationException,异常//int[] nums = {2,4,5};Integer[] nums = {2,4,5};List<Integer> li = Arrays.asList(nums);sop(li);}//contains方法原理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);}}
集合变数组,Collection接口中的toArray方法。
1、指定类型的数组到底要定义多长呢?
      当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
      当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。所以创建一个刚刚好的数组最优。
2、为什么要将集合变数组?
      为了限定对元素的操作。不需要进行增删了。
import java.util.*;class  CollectionToArray{public static void main(String[] args) {ArrayList<String> al = new ArrayList<String>();  //创建一个ArrayList集合al.add("abc1");al.add("abc2");al.add("abc3");String[] arr = al.toArray(new String[al.size()]);  //al.size获取集合长度,以便正好转换后的数组正好 装下System.out.println(Arrays.toString(arr));}}

高级for循环

格式:
for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)
{

}
对集合进行遍历,只能获取集合元素。但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
import java.util.*;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());}*/
用高级for循环对map集合的操作
import java.util.*;class  TestWork{public static void main(String[] args) {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)   //遍历返回的set集合{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());}}}

传统for和高级for有什么区别呢?
高级for有一个局限性。必须有被遍历的目标。
建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
可变参数
一种数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可,隐式将这些参数封装成了数组。
注意:可变参数一定要定义在参数列表最后面。
class  TestWork{public static void main(String[] args) {show("haha",2,3,4,5,6);show("lala",1,24,6);}public static void show(String str,int... arr){System.out.println(arr.length);}}

静态导入

import java.util.*;import static  java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。import static java.util.Collections.*;import static  java.lang.System.*;//导入了System类中所有静态成员。class  StaticImport //extends Object{public static void main(String[] args) {out.println("haha");  //静态导入了System类中所有静态成员之后不需要加System.了int[] arr = {3,1,5};sort(arr);int index = binarySearch(arr,1); //Arrays.out.println(Arrays.toString(arr));  //因为Object类中也有toString方法,所以这里必须要标识ArraysSystem.out.println("Index="+index);ArrayList<Integer> al = new ArrayList<Integer>();al.add(1);al.add(3);al.add(2);out.println(al);sort(al);  //Collections.out.println(al);}}
注意:
当类名重名时,需要指定具体的包名,当方法重名是,指定具备所属的对象或者类。


















0 0
原创粉丝点击