极客java12

1.Iterator接口

  • Iterable接口:实现这个接口就可以支持forEach循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.geekboys.learnlist.mylist;

import java.util.*;

public class MyArrayList<T> implements List {
private Object[] elements;
private int curr;

public MyArrayList() {
this.elements = new Object[16];
curr =0;
}

@Override
public int size() {
return curr;
}

@Override
public boolean isEmpty() {
return curr == 0;
}

@Override
public boolean contains(Object o) {
for (Object ele : elements) {
if (Objects.equals(ele,o)) {
return true;
}
}
return false;
}

// TODO 实现iterable接口里定义的iterator接口
@Override
public Iterator<T> iterator() {
return new Iterator<>() {
int pointer = 0;

@Override
public boolean hasNext() {
return pointer < size();
}

@Override
public T next() {
return (T) elements[pointer++];
}
};
}

@Override
public Object[] toArray() {
return new Object[0];
}

@Override
public Object[] toArray(Object[] a) {
return new Object[0];
}

@Override
public void clear() {
curr = 0;
}

@Override
public Object get(int index) {
if (index > curr || index < 0) {
throw new IndexOutOfBoundsException("Out of bound"+curr+" for " + index);
}
return elements[index];
}

@Override
public boolean add(Object o) {
if (curr == elements.length-1) {
Object[] temp = new Object[elements.length * 2];
for (int i = 0;i < elements.length;i++) {
temp[i] = elements[i];
}
elements = temp;
}elements[curr] = o;
curr++;
return true;
}


}

2.Map:key和value的映射

  • Map和List一样,是一种最基础的数据结构,它描述的是key-value一一对应的数据结构,每种高级语言都有Map的定义和实现
  • 使用自己写的类作为key,必须保证hashCode和equals方法实现的妥妥的,而且一定是不可变的。如果作为key的对象是可以改变的
    • put方法就是向里面增加一个key和value的
    • containsKey检查里面有没有这个key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.geekboys.learnmap;

import java.util.HashMap;
import java.util.Map;

public class LearnMapAppMain {
public static void main(String[] args) {
Map<String, String> map = createMap(99);
System.out.println("Map中的元素个数为:" + map.size());
// TODO 通过get方法,得到传递的key对应的value值
// TODO 注意get方法没有使用范型,它的类型是Object
System.out.println(map.get("key20"));
// TODO 如果没有key,或者key的值就是null,那么返回null
System.out.println(map.get(new Object()));
System.out.println(map.get("key999"));
// TODO 注意不是每种Map的实现都允许key或者value为null
map.put(null, "value of null key");
map.put("testnull", null);

System.out.println("null key : " + map.get(null));
System.out.println("null value : " + map.get("testnull"));
// TODO 注意Map是不支持key重复的,value重复是可以的

// TODO 删除key
System.out.println("--------删除key--------");

String keyToRemove = "key9";
System.out.println(keyToRemove + "对应的值为" + map.get(keyToRemove));
map.remove(keyToRemove);
System.out.println("执行删除操作之后 " + keyToRemove + "对应的值为" + map.get(keyToRemove));

System.out.println("--------遍历key和value--------");
// TODO 通过Entry类遍历Map
for (Map.Entry<String,String> entry : map.entrySet()) {
System.out.println("key为:"+entry.getKey()+"value为:" + entry.getValue());
}

System.out.println("------遍历key-------");
for (String key : map.keySet()) {
System.out.println(key);
}
System.out.println("------遍历value-------");
for (String value : map.values()) {
System.out.println(value);
}
}

public static Map<String, String> createMap(int size) {
Map<String, String> ret = new HashMap<>();
for (int i = 0; i < size; i++) {
ret.put("key" + i, String.valueOf(Math.random()));
}
return ret;
}
}

3.定义i自己的注解

  • 注解的英文名字叫annotation。是给类,方法以及成员变量增加元数据(matedata)的方式.换言之,就是描述这些元素的,和注释不同的是,这些描述会被Java编译器处理而非跳过
  • 最常见的两个注解可能是Override(覆盖)和Deprecated(过时)
  • 注解只是一种metadata传递渠道,本身没有实现功能
  • 注解背后具体的功能,还要用代码读取注解,然后根据注解来实现功能,所以每个注解的具体功能要分别学习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.geekboys.learnannotation;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//TODO 注解可以被用在那些元素上
@Target(ElementType.METHOD)
//TODO 注解可以被留存到那些阶段
@Retention(RetentionPolicy.RUNTIME)
//TODO 以上的两个注解是每个元素都必须要有的

//TODO 定义一个自己的注解,需要@interfae,实际上这个接口会继承Annotation接口
public @interface PrimaryProperty {
// TODO 注解支持的类型有基本数据类型,Class,String,枚举,其他枚举,以上类型的数组
// TODO 可以指定缺省值
String defaultValue() default "N/A";

Class targetClass();

int abc();

String[] defaultValues();

//TODO 注解类型的缺省值
Override is() default @Override;
}
  • 使用注解
1
2
3
4
5
6
7
8
9
10
11
package com.geekboys.learnannotation;
public class TestUseAnnotation {

private Object abc;

// TODO 给annotation里的属性赋值的方式
@Deprecated
@PrimaryProperty(defaultValue = "test",targetClass = TestUseAnnotation.class,
abc = 9,defaultValues = {"aaa","bbb"})
public void test() {}
}
  • 获取注解内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.geekboys.learnannotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class ReadAnnotationAppMain {
public static void main(String[] args) throws NoSuchMethodException {
Class clazz = TestUseAnnotation.class;
Method method = clazz.getMethod("test");
for (Annotation annotation : method.getAnnotations()) {
System.out.println(annotation.annotationType());
}
PrimaryProperty primaryProperty = method.getAnnotation(PrimaryProperty.class);
System.out.println(primaryProperty.abc());
System.out.println(primaryProperty.defaultValue());
}
}

4.lambda的理解和使用(上)

  • lambda 是函数式编程。很多语言中函数(方法)是一等公民, 无需依附于任何其他元素即可存在,并可以作为参数和返回值,而java只有类是一等公民,方法必须依附于某个类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.geekboys;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class IterateListLambdaAppMain {
public static void main(String[] args) {
List<String> myList = addElementsToList(new ArrayList<>());
// for (String str: myList) {
// System.out.println(str);
// }
String outside = "outside string";
// TODO 匿名内部类版
// myList.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// processString(outside+s);
// }
// });
// TODO lambda的表达式必须能符合接口中定义的抽象方法,从参数到返回值,到异常都必须匹配
// TODO lambda 完整版(参数) -> 代码块
// TODO lambda 可以有返回值,使用return就可以
// TODO lambda 可以使用外部数据,和内部匿名类一样的

// myList.forEach((s) -> {
// processString(outside+s);
// });

// TODO lambda 单参数,代码单行简化版
myList.forEach(s->processString(outside + s));

// TODO lambda 如果不适用外部变量,还有方法引用终极简化版
// myList.forEach(IterateListLambdaAppMain::processString);

// TODO lambda 方法引用终极简化版,不是静态方法,用引用也可以
IterateListLambdaAppMain inst = new IterateListLambdaAppMain();
myList.forEach(inst::processStringInst);
// TODO lambda 也允许指定一个参数类型里的一个方法作为方法的引用
myList.forEach(String::toUpperCase);
myList.forEach(s->processString(s));

Map<String,String> myMap = new HashMap<>();
myMap.put("k1","v1");
myMap.put("k2","v2");
myMap.put("k3","v3");
// TODO 两个参数也没问题,把参数用括号括起来,用都好分开
myMap.forEach((k,v) -> processTwoStrings(k,v));

}
public static List<String> addElementsToList(List<String> list) {
for (int i= 0;i< 22;i++) {
list.add("str" + i);
}
return list;
}
public static void processString(String str) {
System.out.println(str);
}
public void processStringInst(String str) {
System.out.println(str);
}
public static void processTwoStrings(String str1,String str2) {
System.out.println("s1=" + str1+", s2="+str2);
}
}

5.lambdda的理解和使用(下)

  • lambda相当于是Java通过后台操作帮我们生成一个类来实现接口,并调用我们提供的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.geekboys;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class IterateListLambdaAppMain {
public static void main(String[] args) {
List<String> myList = addElementsToList(new ArrayList<>());
// for (String str: myList) {
// System.out.println(str);
// }
String outside = "outside string";
// TODO 匿名内部类版
// myList.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// processString(outside+s);
// }
// });
// TODO lambda的表达式必须能符合接口中定义的抽象方法,从参数到返回值,到异常都必须匹配
// TODO lambda 完整版(参数) -> 代码块
// TODO lambda 可以有返回值,使用return就可以
// TODO lambda 可以使用外部数据,和内部匿名类一样的

// myList.forEach((s) -> {
// processString(outside+s);
// });

// TODO lambda 单参数,代码单行简化版
myList.forEach(s->processString(outside + s));

// TODO lambda 如果不适用外部变量,还有方法引用终极简化版
// myList.forEach(IterateListLambdaAppMain::processString);

// TODO lambda 方法引用终极简化版,不是静态方法,用引用也可以
IterateListLambdaAppMain inst = new IterateListLambdaAppMain();
myList.forEach(inst::processStringInst);
// TODO lambda 也允许指定一个参数类型里的一个方法作为方法的引用
myList.forEach(String::toUpperCase);
myList.forEach(s->processString(s));

Map<String,String> myMap = new HashMap<>();
myMap.put("k1","v1");
myMap.put("k2","v2");
myMap.put("k3","v3");
// TODO 两个参数也没问题,把参数用括号括起来,用都好分开
myMap.forEach((k,v) -> processTwoStrings(k,v));

}
public static List<String> addElementsToList(List<String> list) {
for (int i= 0;i< 22;i++) {
list.add("str" + i);
}
return list;
}
public static void processString(String str) {
System.out.println(str);
}
public void processStringInst(String str) {
System.out.println(str);
}
public static void processTwoStrings(String str1,String str2) {
System.out.println("s1=" + str1+", s2="+str2);
}
}
  • 异常的发生
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.geekboys;

import java.util.ArrayList;
import java.util.List;

public class IterateListLambdaWhereAppMain {
public static void main(String[] args) {
List<String> myList= addElementsToList(new ArrayList<>());
// TODO action.accept 就直接跳到了我们的放啊发,其实中间Java一顿后台操作帮我们生成了一个匿名类
// TODO 并调用我们提供的方法
myList.forEach(IterateListLambdaWhereAppMain::processString);
}

public static List<String> addElementsToList(List<String> list) {
for (int i = 0; i < 10; i++) {
list.add("str" + (i % 5));
}
return list;
}
private static void processString(String str) {
throw new RuntimeException();
}
}
  • UseStream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.geekboys;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.geekboys.IterateListLambdaAppMain.addElementsToList;

public class UseStreamAppMain {
public static void main(String[] args) {
List<String> myList = addElementsToList(new ArrayList<>());
System.out.println("----lambda的奥义----");
// TODO lambda的奥义是使用lambda一个接着一个处理,不要停,知道业务结束
// TODO 理性来说,lambda结构对计算优化是友好的,感性来说,这种方式会产生美
myList.stream().filter(s->s.length() > 4).map(String::toUpperCase).forEach(System.out::println);
// TODO 当然也可以使用collector让数据重新生成一个List
System.out.println("----使用collector----");
List<String> longgerStrList = myList.stream().filter(s->s.length() > 4)
.map(String::toUpperCase).collect(Collectors.toList());
longgerStrList.forEach(System.out::println);
}
}
  • 理解lambda的精髓:让代码脱离类的束缚,自由的飞翔,这样就可以把代码传递给数据提供方,而不是只能把数据给代码,通过这种方法,达到链式处理数据

6.基本类型的自动装箱与拆箱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.geekboys;

import java.util.HashMap;
import java.util.Map;

public class WrapperClassesForNumberPrimaryTypesAppMain {
public static void main(String[] args) {
// TODO 从java第一个版本开始,java就为每种基本数据类型提供了封装的类,以便可以将其作为类而非基本数据类型使用
// TODO 比如List Map这些类,都是操作的Object,无法操作基本数据类型
// TODO 和数字相关的基本数据类型对应的类依次是:Byte Short Integer Long Float Double
int a = 99;
// TODO 可以使用数字创建一个Integer类,下面的方法在别的数字类中也都类似
Integer i1 = new Integer(a);
Integer i2 = new Integer("789");
int b = Integer.valueOf(a);
int c = Integer.parseInt("999");
System.out.println("----自动封箱拆箱----");
// TODO java提供了自动为每种基本数据类型和其封装类之间的转换功能
// TODO 从基本数据类型到封装类 叫自动封箱auto boxing,反之叫自动拆箱auto unboxing
Integer ab = 987;
int cd = ab;

// TODO 自动封箱为Integer,作为Map中的key
Map<Integer,String> int2Str = new HashMap<>();
int2Str.put(1,"壹");
int2Str.put(2,"二");
int2Str.put(3,"叁");
System.out.println(int2Str.get(1));

// TODO 自动拆箱为int
for (int key: int2Str.keySet()) {
System.out.println(key);
}
System.out.println("-----有用的方法-----");
System.out.println(Integer.toBinaryString(1024));
System.out.println(Integer.toOctalString(1024));
System.out.println(Integer.toHexString(1024));

System.out.println("----num类-----");
Number num = 9;
num = new Integer(12345);
Number numD = new Double(12.34);
// TODO 使用Number类可以方便的进行数字类型的转换
// TODO 当然所有的类都继承了Number的这些转换方法
System.out.println("使用number将double转为long:"+ numD.longValue());

System.out.println("----自动拆箱可能为NPE----");
int2Str.put(null,"无");
System.out.println(int2Str.get(null));
// TODO 自动拆箱为int,并给key赋值,但是key为null,是无法转为int的, 注意:null不是0
// TODO 其实自动拆箱,后面是java帮我们自动调用了对应的方法,这里就是inValue()这个方法
// TODO 所以放引用为null时自动拆箱,相当于是调用null的方法,所以这个时候发生npe
// TODO 对于其他封装类型的自动拆转箱,也是一样的
for (int key: int2Str.keySet()
) {
System.out.println(key);
}
}
}
  • 字符中的方法
1
2
3
4
5
6
7
8
9
10
11
12
package com.geekboys;

public class WrapperClassForCharAppMain {
public static void main(String[] args) {
// TODO char对应的类为Character,里面有很多isXX方法比较实用
System.out.println(Character.isDigit('A'));
System.out.println(Character.isDigit('字'));
System.out.println(Character.isDigit('0'));
System.out.println(Character.isDigit('6'));

}
}
  • Boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.geekboys;

public class WrapperClassForBooleanAppMain {
public static void main(String[] args) {
// TODO boolean对应的类为Boolean,布尔值只有两个值,所以Boolean类直接提供了这两个值的静态变量
System.out.println("----静态变量-------");
System.out.println(Boolean.TRUE);
System.out.println(Boolean.FALSE);

System.out.println("------valueOf-----");
// TODO 只有不分大小写的true才是true,剩下的都是false
System.out.println(Boolean.valueOf("true"));
System.out.println(Boolean.valueOf("false"));
System.out.println(Boolean.valueOf("TRue"));
}
}

Java中的文件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.geekboys;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class CreateDirAndFileAppMain {
private static final String ROOT = "." + File.separator;
private static Scanner scanner = new Scanner(System.in);

public static void main(String[] args) throws IOException {
File dir = createDirs();
File newDir = renameDir(dir);
if (newDir == null) return;
String fileName = createFiles(newDir);
deleteFiles(newDir,fileName);
deleteDir(newDir);
}

public static File createDirs() {
List<String> pathList = new ArrayList<>();
while (true) {
System.out.println("请输入文件名,如果为空格则结束");
String path = scanner.nextLine();
if (path.isBlank()) {
break;
}
pathList.add(path);
}
return createDir(pathList.toArray(new String[0]));
}
private static File createDir(String... restPaths) {
String rest = joinRestDir(restPaths);
System.out.println("将在"+ROOT+"下创建"+rest);
File dir = new File(ROOT,rest);
if (dir.exists() && dir.isDirectory()) {
System.out.println("文件夹已经存在"+dir.toString());
return dir;
} else {
boolean createSuccess = dir.mkdirs();
if (createSuccess) {
return dir;
} else {
throw new IllegalArgumentException("无法在"+ROOT+"下创建"+rest);
}
}

}
private static String joinRestDir(String... restPaths) {
return Arrays.stream(restPaths).map(String::trim).collect(Collectors.joining(File.separator));
}

private static File renameDir(File dir) {
System.out.println("请输入新的文件夹名字:");
String newDirName = scanner.nextLine().trim();

File newDir = new File(dir.getParent(),newDirName);
boolean renameSuccess = dir.renameTo(newDir);
if (renameSuccess) {
System.out.println("改名为"+newDirName+"成功");
} else {
System.out.println("改名为"+ newDirName+"失败");
return null;
}
return newDir;

}
public static String createFiles(File newDir) throws IOException {
System.out.println("请输入文件名前缀:");
String fileName = scanner.nextLine().trim();
for (int i= 0;i < 20;i++) {
File f = new File(newDir,fileName + i +".txt");
System.out.println("创建文件"+f.getName()+":"+f.createNewFile());
}
return fileName;
}
public static String renameFiles(File newDir,String fileName) {
System.out.println("请输入新的文件名前缀:");
String fileNameNew = scanner.next().trim();
for (int i= 0;i<20;i++) {
File f = new File(newDir,fileName+i+".txt");
File fn = new File(newDir,fileNameNew+i+".txt");
System.out.println("重命名文件"+f.getName()+":"+f.renameTo(fn));
}
return fileNameNew;
}
public static void deleteFiles(File newDir,String fileNameNew) {
System.out.println("删除文件?");
boolean deleteFiles = scanner.nextBoolean();

if (deleteFiles) {
for (int i= 0;i< 20;i++) {
File fn = new File(newDir,fileNameNew+i+".txt");
System.out.println("删除文件"+fn.delete());
}
}
}
public static void deleteDir(File newDir) {
System.out.println("删除文件夹");
boolean deleteDir = scanner.nextBoolean();
if (deleteDir) {

System.out.println("删除文件夹" + newDir.delete());
}
}

}
你的支持是我最大的动力!
0%