------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
第一讲、Map集合
一、概述
Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1、常用方法:
a.添加
put(K key,V value) 将指定的值与此映射中的指定键关联(可选操作)。
putAll(Map<? extends K,? extends V> m)从指定映射中将所有映射关系复制到此映射中(可选操作)。
b.删除
clear()从此映射中移除所有映射关系(可选操作)。
remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
c.判断
containsKey(Object key)如果此映射包含指定键的映射关系,则返回 true。
containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
isEmpty()如果此映射未包含键-值映射关系,则返回 true。
d.获取
get(Object key)返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
size()返回此映射中的键-值映射关系数。
values()
e.重点:entrySet()返回此映射中包含的映射关系的 Set 视图。
keySet()返回此映射中包含的键的 Set 视图。
2、Map集合常用子集
Map
|--Hashtable:底层时哈希表数据结构,不可以存入null键null值。该集合时线程同步的JDK1.0效率低
|--HashMap:底层是哈希表数据结构,并允许使用null键和null值,该集合是不同步的JDK1.2效率高
|--TreeMap:底层时二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序
和Set很像。其实Set底层就是使用了Map集合。
import java.util.*; class MapDemo { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); //添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值 System.out.println("put:"+map.put("01","zhangsan1")); System.out.println("put:"+map.put("01","wangwu")); map.put("02","zhangsan2"); map.put("03","zhangsan3"); System.out.println("containsKey:"+map.containsKey("02")+"containsValue:"+map.containsValue("zhangsan3")); //将键值对删除,并返回键所对应的值 //System.out.println("remove:"+map.remove("02")); System.out.println("get:"+map.get("023")); map.put(null,"haha"); System.out.println("get:"+map.get(null)); //可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断 //获取map集合中所有的值。 Collection<String> coll = map.values(); System.out.println(coll); System.out.println(map); } }
3、map集合的两种取出方式:
a.Set<K> keySet:将map中所有的键存入到Set集合,因为set具备迭代器,所以可以迭代方式取出所有键,在根据get方法 ,获取每一个键对应的值。
Map集合的取出原理:将Map集合转成Set集合,在通过迭代器取出。
b.Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型是:Map.Entry
import java.util.*; class MapDemo2 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("02","zhangsan2"); map.put("03","zhangsan3"); map.put("01","zhangsan1"); map.put("04","zhangsan4"); //将map集合中的映射关系取出,存入到Set集合中。 Set<Map.Entry<String,String>> entrySet = map.entrySet(); Iterator<Map.Entry<String,String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<String,String> me = it.next(); String key = me.getKey(); String value = me.getValue(); System.out.println(key+":"+value); } /* //先获取map集合的所有键的Set集合,keySet(); Set<String> keySet = map.keySet(); //有了Set集合,就可以获取其迭代器。 Iterator<String> it = keySet.iterator(); while(it.hasNext()) { String key = it.next(); //有了键可以通过map集合的get方法获取其对应的值 String value = map.get(key); System.out.println("key:"+key+"value:"+value); } */ } } /* Map.Entry其实Entry也是一个接口,他是Map接口中的一个内部接口。 interface Map { public static interface Entry { public abstract Object getKey(); public abstract Object getValue(); } } class HashMap implements Map { class HaHa implements Map.Entry { public Object getKey(); public Object getValue(); } } */
练习:
/* 每一个学生都有对应的归属地。 学生Student,地址String。 学生属性:姓名,年龄。 注意:姓名和年龄相同的视为同一个学生。 保证学生的唯一性。 1.描述学生。 2.定义map容器,将学生作为键,地址作为值,存入。 3.获取map集合中的元素。 */ import java.util.*; class Student implements Comparable<Student> { private String name; private int age; Student(String name,int age) { this.name = name; this.age = age; } //防止存入二叉树中,让其存在自然排序 public int compareTo(Student s) { int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num==0) return this.name.compareTo(s.name); return num; } public int hashCode() { return name.hashCode()+age*34; } public boolean equals(Object obj) { if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.age==s.age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name+"::"+age; } } class MapTest { public static void main(String[] args) { HashMap<Student,String> hm = new HashMap<Student,String>(); hm.put(new Student("lisi1",21),"beijing"); hm.put(new Student("lisi2",22),"shanghai"); hm.put(new Student("lisi3",23),"nanjing"); hm.put(new Student("lisi4",24),"wuhan"); //第一种取出方式keySet Set<Student> keySet=hm.keySet(); Iterator<Student> it = keySet.iterator(); while(it.hasNext()) { Student stu = it.next(); String addr = hm.get(stu); System.out.println(stu+":::"+addr); } //第二种取出方式 entrySet Set<Map.Entry<Student,String>> entrySet=hm.entrySet(); Iterator<Map.Entry<Student,String>> iter = entrySet.iterator(); while(iter.hasNext()) { Map.Entry<Student,String> me = iter.next(); Student stu=me.getKey(); String addr = me.getValue(); System.out.println(stu+":::::::"+addr); } } }
练习2:
/*
“sdfqzxcvasdfxcvdf”获取该字符串中的字母出现的次数。 希望打印结果:a(1)c(2)... 通过结果发现,每一个字母都有对应的次数。 说明字母和次数之间都有映射关系。 注意:当发现有映射关系时,可以选择map集合。 因为map集合中存放就是映射关系。 什么时候使用映射集合呢? 当数据之间存在着映射关系时,就要先想map集合。 思路: 1.将字符串转换成字符数组,因为要对每一个字母进行操作。 2.定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。 3.遍历字符数组。 将每一个字母作为键去查map集合。 如果返回null,将该字母和1存入到map集合中。 如果返回不是null,说明该字母在map集合中已经存在并有对应次数。 那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到map集合中,覆盖调用原有键的值 4.将map集合中的数据变成指定的字符串形式返回。 */ import java.util.*; class MapTest3 { public static void main(String[] args) { String s = charCount("aabfddabcdefa"); System.out.println(s); } public static String charCount(String str) { char[] chs = str.toCharArray(); //<基本数据类型> TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>(); int count = 0; for(int x=0;x<chs.length;x++) { if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z')) continue; Integer value = tm.get(chs[x]); if(value!=null) count = value; count++; tm.put(chs[x],count); count = 0; /* if(value==null) { tm.put(chs[x],1); } else { value = value +1; tm.put(chs[x],value); } */ } //System.out.println(tm); StringBuilder sb = new StringBuilder(); Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet(); Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<Character,Integer> me = it.next(); Character ch = me.getKey(); Integer value = me.getValue(); sb.append(ch+"("+value+")"); } return sb.toString(); } }
二、Map扩展知识
/* map集合被使用是因为具备映射关系. "yureban" "01" "zhangan"; "yureban" "02" "lisi"; "jiuyeban" "01" "wangwu"; "jiuyeban" "02" "zhaoliu" 一学校有多个教室。一个教室有多个学生 */ import java.util.*; class Student { private String id; private String name; Student(String id,String name) { this.id = id; this.name = name; } public String toString() { return id+":"+name; } } class MapDemo3 { public static void demo() { HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>(); List<Student> yure = new ArrayList<Student>(); List<Student> jiuye = new ArrayList<Student>(); czbk.put("yureban",yure); czbk.put("jiuyeban",jiuye); yure.add(new Student("01","zhangsan")); yure.add(new Student("04","wangwu")); jiuye.add(new Student("01","zhouqi")); jiuye.add(new Student("02","zhaoli")); Iterator<String> it = czbk.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); List<Student> room = czbk.get(roomName); System.out.println(roomName+":"+room); getInfos(room); } } public static void getInfos(List<Student> list) { Iterator<Student> it = list.iterator(); while(it.hasNext()) { Student s= it.next(); System.out.println(s); } } public static void main(String[] args) { demo(); /* HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>(); HashMap<String,String> yure = new HashMap<String,String>(); HashMap<String,String> jiuye = new HashMap<String,String>(); czbk.put("yureban",yure); czbk.put("jiuyeban",jiuye); yure.put("01","zhangsan"); yure.put("02","lisi"); jiuye.put("01","wangwu"); jiuye.put("02","zhaoliu"); //System.out.println(czbk); //遍历czbk集合,获取所有教室 Iterator<String> it = czbk.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); HashMap<String,String> room = czbk.get(roomName); System.out.println(roomName+":"+room); } getStudentInfo(yure); */ } public static void getStudentInfo(HashMap<String,String> roomMap) { Iterator<String> it =roomMap.keySet().iterator(); while(it.hasNext()) { String id = it.next(); String name = roomMap.get(id); System.out.println(id+":"+name); } } }
第二讲、工具类
一、Collections类
Collections
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
集合框架的工具类。Collections:
常用方法演示:
import java.util.*; class CollectionsDemo { public static void main(String[] args) { //sortDemo(); //maxDemo(); binarySearchDemo(); } //二分查找,List必须是有序的 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,"aaa"); //int index = halfSearch(list,"aaa"); //int index = halfSearch2(list,"zz",new StrLenComparator()); sop("index="+index); } //binarySearch原理; public static int halfSearch(List<String> list,String key) { int max,min,mid; max = list.size()-1; min = 0; while(min<max) { mid = (min+max)>>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; } 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 = (min+max)>>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; else return mid; } return -min-1; } //根据元素的自然顺序,返回给定 collection 的最大元素。 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); Collections.sort(list,new StrLenComparator()); 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.*; class CollectionsDemo2 { public static void main(String[] args) { replaceAllDemo(); } //使用另一个值替换列表中出现的所有某一指定值。 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"); //将集合中的元素全部替换成“pp”; sop(list); } public static void sop(Object obj) { System.out.println(obj); } }
reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
reverseOrder(Comparator<T> cmp)
返回一个比较器,它强行逆转指定比较器的顺序。
import java.util.*; //定义一个自然顺序比较器 class StrComparator implements Comparator<String> { public int compare(String s1,String s2) { return s1.compareTo(s2); } } //定义一个长度比较器 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 CollectionsDemo3 { 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"); //Collections.sort(list); sop(list); <span style="white-space:pre"> </span>//随机排序 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); } }
二、Arrays
Arrays:用于操作数组的工具类。里面都是静态方法。
asList:将数组变成list集合
import java.util.*; class ArraysDemo { public static void main(String[] args) { // int[] arr = {1,2,3}; // System.out.println(Arrays.toString(arr)); String[] arr = {"abc","cc","kkkk"}; //把数组变成list集合有什么好处? /* 可以使用集合的思想和方法来操作数组中的元素。 contains. get indexOf(0 subList(); 注意:将数组变成集合,不可以使用集合的增删方法。 因为数组的长度是固定的。 如果增删,那么会发生UnsupportedOperationException. 不支持异常 */ List<String> list= Arrays.asList(arr); //sop("contains+"+list.contains("cc")); //list.add("qq");错误 //sop(list); //int[] nums = {1,2,3}; //此时li中只有一个元素,就是nums数组的地址值 //List<int[]> li = Arrays.asList(nums); Integer[] nums = {1,2,3}; 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); } }
/* 集合变数组。 Collection接口中的toArray方法。 Object[] toArray() 返回包含此 collection 中所有元素的数组。 <T> T[] toArray(T[] a) 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 */ 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"); /* 1.指定类型的数组到底要定义多长呢? 当指定类型的数组长度小于了集合的size,那么该方法内部都会创建一个新的数组,长度为集合的size。 当指定类型的数组长度大于了集合的size,就不会创建新数组,而是使用传递进来的数组。 所以创建一个刚刚好的数组最优。 2.为什么要将集合变数组? 为了限定对元素的操作。不需要进行增删了。 */ String[] arr = al.toArray(new String[al.size()]); System.out.println(Arrays.toString(arr)); } }
三、增强for循环
高级for循环
格式:
for(数据类型 变量名:被遍历的集合(Collection)或者数组)
{}
对集合进行遍历。只能获取元素,但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。
如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
传统for循环和高级for有什么区别呢?
高级for有一个局限性。必须有被遍历的目标。
建议在遍历数组的时候,还是希望使用传统for,因为传统for可以定义角标
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) { System.out.println(s); } int[] arr = {3,5,1}; 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()); } /* Iterator<String> it = al.iterator(); while(it.hasNext()) { System.out.println(it.next()); } */ } }
四、JDK1.5出现的新特性。
1、方法的可变参数。
在使用时注意:可变参数一定要定义在参数列表的最后面。
class ParamMethodDemo { public static void main(String[] args) { //show(3,4); /* //虽然少定义了多个方法。 但是每次都要定义一个数组,作为实际参数。 int[] arr = {3,4}; show(arr); int[] arr1 = {3,4,5,6}; show(arr1); */ /* 可变参数。 其实就是上一种数组参数的简写形式。 不用每一次都手动的建立数组对象。 只要将要操作的元素作为参数传递即可。 隐式的将这些参数封装成了数组。 */ show("haha",22,3,4,4,5); //show(1,2,3,4,5,56,6,7,7,7); //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); } */ }
2、StaticImport 静态导入
当类名重名时,需要指定具体的包名,
当方法重名时,指定具体所属的对象或者类。
import java.util.*;
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。
import static java.lang.System.*;//导入了System类中所有静态成员。
class StaticImport
{
public static void main(String[] args)
{
int[] arr = {3,1,5};
//排序
Arrays.sort(arr);
int index = binarySearch(arr,1);
//因为Object包中也有toString()方法,所以这是要指定具体类名
System.out.println(Arrays.toString(arr));
System.out.println("index="+index);
out.println("haha");
}
}
第三讲、其他对象
一、1、System类
System 类包含一些有用的类字段和方法。它不能被实例化。
System:类中的方法和属性都是静态的
out:代表标准输出,默认是控制台。
in:标准输入,默认键盘。
描述系统一些信息。
获取系统属性信息:Properties getProperties();
import java.util.*; class SystemDemo { public static void main(String[] args) { Properties prop = System.getProperties(); //因为Properties是Hashtable的子类,也就是Map集合的子类对象。 //那么可以通过map的方法取出该集合中的元素。 //该集合中存储都是字符串,没有泛型定义。
<span style="white-space:pre"> </span><pre name="code" class="java" style="font-size:18px;">/* //获取所有属性信息 for(Object obj : prop.keySet()) { String value =(String)prop.get(obj); System.out.println(obj+"::"+value); }
*/
//如何在系统中自定义一些特有的信息呢?
System.setProperty("myKey","myValue");
//获取指定属性信息
String value = System.getProperty("os.name");
System.out.println("value="+value);
//可不可以在jvm启动时,动态加载一些属性信息呢?
//java -D(name)=(value) SystemDemo就可以动态加载一些属性
String v = System.getProperty("haha");
System.out.println("v="+v);
}
}
2、RunTime对象
该类中并没有提供构造函数。
说明不可以new对象,那么会直接想到该类中的方法都是静态的。
发现该类中还有非静态方法。
说明该类肯定会提供了方法获取本类对象,而且该方法是静态的,并返回值类型是本类类型。
由这个特点可以看出该类使用了单例设计模式完成。
该方法是static RunTime getRunTime();
class RuntimeDemo { public static void main(String[] args) throws Exception { //exec(String command) 在单独的进程中执行指定的字符串命令。 Runtime r = Runtime.getRuntime(); Process p = r.exec("notepad.exe SystemDemo.java"); Thread.sleep(4000); p.destroy(); } }
3、Date类
类 Date 表示特定的瞬间,精确到毫秒。
import java.util.*; import java.text.*; class DateDemo { public static void main(String[] args) { Date d = new Date(); System.out.println(d); //打印的时间看不懂,希望有些格式。 //将格式封装成SimpleDateFormat对象中。 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss"); //调用format方法让模式格式化指定Date对象 String time = sdf.format(d); System.out.println("time:"+time); } }
4、Calendar类
import java.util.*; import java.text.*; /* 1.获取任意一年的二月有多少天。 思路:根据指定年设置一个时间就是 c.set(year,2,1)//某一年的3月1日 c.add(Calendar.DAY_OF_MONTH,-1);//3月1日,往前推一天就是2月的最后一天。 2.获取昨天的这个时刻。 思路: c.add(Calendar.DAY_OF_MONTH,-1) */ class CalendarDemo2 { public static void main(String[] args) { Calendar c = Calendar.getInstance(); sop(c); // c.set(2012,2,23); //根据日历的规则,为给定的日历字段添加或减去指定的时间量。 c.add(Calendar.MONTH,-6); printCalendar(c); } public static void printCalendar(Calendar c) { String[] mons = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"}; int index = c.get(Calendar.MONTH); sop(c.get(Calendar.YEAR)+"年"); //sop((c.get(Calendar.MONTH)+1)+"月"); sop(mons[index]); sop(c.get(Calendar.DAY_OF_MONTH)+"日"); sop("星期"+(c.get(Calendar.DAY_OF_WEEK)-1)); } public static void sop(Object obj) { System.out.println(obj); } }
5、Math类
/* 练习:给定一个小数。 保留该小数的后两位。 */ import java.util.*; class MathDemo { public static void main(String[] args) { Random r = new Random();//此类的实例用于生成伪随机数流。 for(int x=0;x<10;x++) { //double d = Math.random(); int d = r.nextInt(10); sop(d); } } public static void show() { double d = Math.ceil(-16.34);//ceil返回大于指定数据的最小整数。 double d1 = Math.floor(12.34);//ceil返回小于指定数据的最大整数。 long l = Math.round(12.34);//四舍五入; sop("d:"+d); sop("d1:"+d1); sop("l:"+l); double d2 = Math.pow(2,3);//返回第一个参数的第二个参数次幂的值。2的3次幂 sop(d2); } public static void sop(Object obj) { System.out.println(obj); } }