Java笔记(五)
泛型:JDK1.5版本后出现的新特性。用于解决安全问题,是一个类型安全机制。
好处:将运行期间出现问题ClassCastException,转移到了编译时期。方便程序员解决问题,让运行时问题减少。
避免了强制转换麻烦。
泛型格式:通过<>来定义要操作的引用数据类型
通常在集合框架中很常见,只要见到<>就要定义泛型。当使用集合时,将集合中要存储的数据类型作为参数传递到<>即可。
泛型类定义的泛型,在整个类中都有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
注:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。泛型定义在方法上时,要写在返回值类型的前面。如:public static <T> void method(T t)
Map集合:该集合存储键值对,一对一往里存。而且要保证键的唯一性。
添加:put(K key, V value) putAll(Map<? extends K, ? extends V> m) 如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,put方法会返回被覆盖的值。
删除:clear() remove(Object key)
判断:containsValue(Object value) containKey(Object key) isEmpty()
获取:get(object key) size() values() entrySet() keySet()
Map
|--Hashtable:底层是hash表数据结构,不可以存入null键和null值。该集合是线程同步的。jdk1.0 效率低
|--HashMap:底层是hash表数据结构,可以存入null键和null值。该集合是线程不同步的。jdk1.2 效率高
|--TreeMap:底层是二叉树数据结构,线程不同步。可以用于map集合中的键进行排序。
和Set很像。Set底层就是使用了Map集合。
Map集合的两种取出方式:
(1)Set<k> keySet:将Map中所有的键存入到Set集合。因为Set具备迭代器。所以可以用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。
(2)Set<Map.Entry<k, v>> entrySet:将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是Map.Entry。Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。
例:每一个学生都有对应的归属地。学生Student,地址String。学生属性:姓名,年龄。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
(1)描述学生
(2)定义Map容器。将学生作为键,地址作为值。存入
(3)获取Map集合中的元素。
1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 import java.util.Set; 5 //import java.util.TreeMap; 6 7 class Student implements Comparable<Student>{ 8 private String name; 9 private int age; 10 Student(String name, int age){ 11 this.name = name; 12 this.age = age; 13 } 14 public String getName(){ 15 return name; 16 } 17 public int getAge(){ 18 return age; 19 } 20 public int hashCode(){ 21 return name.hashCode() + age * 34; 22 } 23 public boolean equals(Object obj){ 24 if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); 25 Student s = (Student)obj; 26 return this.name.equals(s.name) && this.age == s.age; 27 } 28 public int compareTo(Student s){ 29 int num = new Integer(this.age).compareTo(new Integer(s.age)); 30 if(num == 0) 31 return this.name.compareTo(s.name); 32 return num; 33 } 34 } 35 36 37 public class Demo{ 38 public static void main(String[] args) { 39 HashMap<Student, String> hm = new HashMap<Student, String>(); 40 41 hm.put(new Student("ztq01", 20), "北京"); 42 hm.put(new Student("ztq02", 21), "上海"); 43 hm.put(new Student("ztq03", 22), "天津"); 44 hm.put(new Student("ztq04", 23), "重庆"); 45 46 //第一种 47 // Set<Student> key = hm.keySet(); 48 // Iterator<Student> it = key.iterator(); 49 // while(it.hasNext()){ 50 // Student s = it.next(); 51 // String value = hm.get(s); 52 // System.out.println(s.getName() + " " + s.getAge() + " ~ " + value); 53 // } 54 55 //第二种 56 Set<Map.Entry<Student, String>> entry = hm.entrySet(); 57 Iterator<Map.Entry<Student, String>> it = entry.iterator(); 58 while(it.hasNext()){ 59 Map.Entry<Student, String> tmp = it.next(); 60 Student key = tmp.getKey(); 61 String value = tmp.getValue(); 62 System.out.println(key.getName() + " " + key.getAge() + " ~ " + value); 63 } 64 } 65 }
用TreeMap实现排序,根据姓名排序
1 import java.util.Comparator; 2 import java.util.HashMap; 3 import java.util.Iterator; 4 import java.util.Map; 5 import java.util.Set; 6 import java.util.TreeMap; 7 8 class Student{ 9 private String name; 10 private int age; 11 Student(String name, int age){ 12 this.name = name; 13 this.age = age; 14 } 15 public String getName(){ 16 return name; 17 } 18 public int getAge(){ 19 return age; 20 } 21 public int hashCode(){ 22 return name.hashCode() + age * 34; 23 } 24 public boolean equals(Object obj){ 25 if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); 26 Student s = (Student)obj; 27 return this.name.equals(s.name) && this.age == s.age; 28 } 29 } 30 31 class stuNameComparator implements Comparator<Student>{ 32 public int compare(Student s1, Student s2){ 33 int num = s1.getName().compareTo(s2.getName()); 34 if(num == 0){ 35 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); 36 } 37 return num; 38 } 39 } 40 41 public class Demo{ 42 public static void main(String[] args) { 43 TreeMap<Student, String> hm = new TreeMap<Student, String>(new stuNameComparator()); 44 45 hm.put(new Student("ztq01", 20), "北京"); 46 hm.put(new Student("ztq03", 22), "天津"); 47 hm.put(new Student("ztq04", 23), "重庆"); 48 hm.put(new Student("ztq02", 21), "上海"); 49 //第一种 50 // Set<Student> key = hm.keySet(); 51 // Iterator<Student> it = key.iterator(); 52 // while(it.hasNext()){ 53 // Student s = it.next(); 54 // String value = hm.get(s); 55 // System.out.println(s.getName() + " " + s.getAge() + " ~ " + value); 56 // } 57 58 //第二种 59 Set<Map.Entry<Student, String>> entry = hm.entrySet(); 60 Iterator<Map.Entry<Student, String>> it = entry.iterator(); 61 while(it.hasNext()){ 62 Map.Entry<Student, String> tmp = it.next(); 63 Student key = tmp.getKey(); 64 String value = tmp.getValue(); 65 System.out.println(key.getName() + " " + key.getAge() + " ~ " + value); 66 } 67 } 68 }
例:“sdfgzxcvasdfxcvdf”获取该字符串中的字母出现的次数,打印结果:a(1)c(2)...
思路:(1)将字符串转换成字符数组。因为要对每个字母进行操作。
(2)定义一个Map集合,因为打印结果的字母有顺序,所以使用TreeMap
(3)遍历字符数组,将每一个字母作为键去查Map集合。如果返回null,就将该字母和1存入到Map集合中。如果返回不为null,说明该字母在Map集合中已经存在并有对应次数。那么就获取该次数并进行自增。然后将该字母和自增后的次数存入Map集合中,覆盖原来键所对应的值。
(4)将Map集合中的数据变成指定的字符串形式返回。
1 import java.util.Iterator; 2 import java.util.Map; 3 import java.util.Set; 4 import java.util.TreeMap; 5 6 public class Demo{ 7 public static void main(String[] args) { 8 String result = charCount("sdfgzxcvasdfxcvdf"); 9 System.out.println(result); 10 } 11 public static String charCount(String s){ 12 char[] arr = s.toCharArray(); 13 TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); 14 for(int i = 0; i < arr.length; i++){ 15 int count = 0; 16 Integer value = tm.get(arr[i]); 17 if(value != null){ 18 count = value; 19 } 20 count++; 21 tm.put(arr[i], count); 22 } 23 StringBuilder sb = new StringBuilder(); 24 Set<Map.Entry<Character, Integer>> entry = tm.entrySet(); 25 Iterator<Map.Entry<Character, Integer>> it = entry.iterator(); 26 while(it.hasNext()){ 27 Map.Entry<Character, Integer> tmp = it.next(); 28 char key = tmp.getKey(); 29 Integer value = tmp.getValue(); 30 sb.append(key + "(" + value + ")"); 31 } 32 return sb.toString(); 33 } 34 }
Collections.sort();
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Comparator; 4 import java.util.List; 5 6 7 public class Demo{ 8 public static void main(String[] args) { 9 List<String> list = new ArrayList<String>(); 10 list.add("abc"); 11 list.add("bc"); 12 list.add("b"); 13 list.add("cccc"); 14 System.out.println(list); 15 Collections.sort(list); 16 System.out.println(list); 17 Collections.sort(list, new StrLenComparator()); 18 System.out.println(list); 19 } 20 } 21 22 class StrLenComparator implements Comparator<String>{ 23 public int compare(String s1, String s2){ 24 int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); 25 if(num == 0){ 26 return s1.compareTo(s2); 27 } 28 return num; 29 } 30 }
输出结果:
[abc, bc, b, cccc]
[abc, b, bc, cccc]
[b, bc, abc, cccc]
Collections.max(list); 同上
Collections.binarySearch(list, 字符串, 比较器); 使用二分搜索法搜索指定列表,以获得指定对象。
Collections.fill(list, 字符串); 把list中的所有元素替换成传入的字符串。
Collections.replaceAll(list, old, new); 使用另一个值替换列表中出现的所有某一指定值。
Collections.reverse(list); 反转指定列表中元素的顺序。
Collections.reverseOrder(); 返回一个比较器,强行逆转实现了Comparable接口的对象collection的自然顺序
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
Collections.swap(list, int i, int j ); 在指定列表的指定位置处交换元素。
Collections.shuffle(list); 使用默认随机源对指定列表进行置换。
Arrays.asList(arr); 将数组变成list集合。
注:将数组变成集合后,不可以使用集合的增删方法。因为数组的长度是固定的。如果增删,则抛出UnsupportedOperationException异常。
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
如:
int[] nums = {1, 2 ,3}; List<int[]> list = Arrays.asList(nums); System.out.println(list); Integer[] numss = {1, 2, 3}; List<Integer> li = Arrays.asList(numss); System.out.println(li);
输出结果:
[[I@6af62373]
[1, 2, 3]
集合变数组:
1 import java.util.ArrayList; 2 import java.util.Arrays; 3 4 public class Demo{ 5 public static void main(String[] args) { 6 ArrayList<String> al = new ArrayList<String>(); 7 al.add("abc1"); 8 al.add("abc2"); 9 al.add("abc3"); 10 /* 11 当指定类型的数组长度小于集合的size, 12 那么该方法内部会创建一个新的数组,长度为集合的size。 13 当指定类型的数组长度大于集合的size, 14 就不会创建新数组,而是使用传递进来的数组。 15 所以创建一个刚好的数组最优。 16 17 集合变数组是为了限定对元素的操作。 18 */ 19 String[] arr = al.toArray(new String[al.size()]); 20 System.out.println(Arrays.toString(arr)); 21 } 22 }
高级for循环:
格式: for(数据类型 变量名:被遍历的集合(Collection)或者数组)
对集合进行遍历。只能获取元素,当时不能对集合进行操作。
可变参数:数组参数的简写形式,不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。使用时,可变参数一定要定义在参数列表后边。
1 public class Demo{ 2 public static void main(String[] args) { 3 show("haha", 1, 2, 3, 4); 4 } 5 public static void show(String s, int ... arr){ 6 System.out.println(arr.length); 7 } 8 }
输出结果:4
System:
out:标准输出,默认是控制台。
in:标准输入,默认是键盘。
描述系统一些信息。
获取系统属性信息:Properties getProperties();
Properties prop = System.getProperties();
因为Properties是Hashtable的子类,也就是Map集合的一个子类对象,那么可以通过Map的方法取出该集合中的元素。该集合中存储的都是字符串。没有泛型定义。
System.setProperty("mykey", "myval"); 自定义一些信息
String value = System.getProperty("os.name"); 获取指定属性信息
Runtime:每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。
该类并没有提供构造函数,说明不可以new对象。所以该类中的方法都是静态的。该类中还有非静态方法,说明该类会提供方法获取本类对象,而且是静态的,返回值类型为本类类型。(单例模式)
static Runtime getRuntime();
Process exec(String command) 在单独的进程中执行指定的字符串命令。
Date:
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 4 public class Demo{ 5 public static void main(String[] args) { 6 Date d = new Date(); 7 System.out.println(d); //无格式 8 9 //将模式封装到SimpleDateFormat对象中 10 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss"); 11 12 //调用format方法,让模式格式化指定Date对象 13 String time = sdf.format(d); 14 System.out.println(time); 15 } 16 17 }
输出结果:
Fri Jan 20 21:39:27 GMT+08:00 2017
2017年01月20日 星期五 21:39:27
Calendar:
1 import java.util.Calendar; 2 3 public class Demo{ 4 public static void main(String[] args) { 5 Calendar c = Calendar.getInstance(); 6 System.out.println(c.get(Calendar.YEAR) + "年"); 7 8 //获取任意年的二月有多少天 9 c.set(2017, 2, 1); //设置某一年3月1日 10 c.add(Calendar.DAY_OF_MONTH, -1); //3月1日往前推一天,就是2月最后一天 11 System.out.println(c.get(Calendar.DAY_OF_MONTH)); 12 } 13 }
输出结果:
2017年
28
Math:
static double ceil(double a) 返回最小的(最接近负无穷大)double值,该值大于等于参数,并等于某个整数。16.34->17
static double floor(double a) 与上边相反。16.34->16
static long round(double a) 返回最接近参数的long(四舍五入) 12.34->12 12.56->13
static double random() 返回带正号的double值(一个伪随机数),该值大于等于0.0,且小于1.0(0.0≤x<1.0)