1. 泛型数组合并
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String[] args){
String[] strArray = {"hello", "world"};
String[] newStrArray = {"like", "love"};
ArrayList<String> list = new ArrayList<>(Arrays.asList(strArray));
list.addAll(Arrays.asList(newStrArray));
String[] resArray = Arrays.copyOf(list.toArray(),list.toArray().length,String[].class);
for(String str:resArray) {
System.out.println(str);
}
}
}
2. 值传递 & 引用传递
2.1 Java数据类型
Java数据类型分为基本数据类型和引用数据类型,如图2-1所示:
![](https://img.haomeiwen.com/i17524543/93a74542f535d5ae.png)
2.2 值传递
值传递:当基本类型作为参数传入方法时,无论该参数在方法内怎样被改变,外部的变量原型总是不变的。即方法操作的是参数变量(也就是原型变量的一个值的拷贝)改变的也只是原型变量的一个拷贝而已,而非变量本身。所以变量原型并不会随之改变。
public class Test {
public void oprNum(int number){
number++;
}
public static void main(String[] args){
int a = 10;
new Test().oprNum(a);
System.out.println(a); //10
}
}
2.3 引用传递
引用传递:当方法传入的参数为非基本类型时(也就是说是一个对象类型的变量), 方法改变参数变量的同时变量原型也会随之改变。方法操作参数变量时是拷贝了变量的引用(指向了对象所在的真实地址,而非对象本身),而后通过引用找到变量的真正地址,并对其进行操作。
public class Test {
public void oprNum(StringBuilder builder){
builder.append("world");
}
public static void main(String[] args){
StringBuilder builder = new StringBuilder("hello");
new Test().oprNum(builder);
System.out.println(builder); //helloworld
}
}
2.4 String参数传递
String的存储实际上通过char[]来实现的,char[]定义为了常量,具有不可变性。当String作为参数传递时,确实是以地址传递过去的,但是在对String类型的变量的值进行改变时,由于String类的值是常量,在创建后不能更改,所以对String参数进行操作,相当于new String(),已经改变了String对象的地址了,所以实参不会改变。
![](https://img.haomeiwen.com/i17524543/cb28a692639b83cc.png)
2.5 String不可变性
所谓的string类型不可变,可以从对象的内存分配上来分析:当创建一个string类型的对象的的时候,如String a=“abc”,首先在“栈”内存中开辟空间保存String类型对象的引用a,且在“常量池”中开辟空间保存内容“abc”。并返回其内存地址给对象的引用a。(a只是字符串内存地址的引用)
当我们在操作a变量的时候,如:1)重新赋值(a=“bbb”),系统会首先查询"常量池",里面是否有”bbb“这个字符串。如果有会自动返回“bbb”这个字符串的地址给对象的引用a。如果没有就会创建字符串“bbb”,并返回地址给对象的引用a。而不是直接操作原对象a指向的保存“abc”内容的这个内存地址空间。从内存分析string是不可变的,指的是对象指向的字符串内容一旦在常量池中被创建和保存,就不会更改。当我们再重新赋值的时候,是给在栈内存中的对象的引用a,赋一个新的地址,而没修改原来值所在空间的地址。
2)使用方法修改其内容(a.replace("a","b");)。对内存的操作是同上的,系统依然会首先在”常量池“中,查找替换后字符串。如果没有找到相应的字符串。就会在常量池中保存一个新的字符串,并返回地址给变量的引用,同样是没有修改“常量池”中原来的值。
当final修饰的变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化。
String.intern()方法在JDK1.7以后,如果字符串在字符串常量池中没有出现过,就会在字符串常量池中保存一个引用,指向堆中该字符串的实例。如果字符串在常量池中已经存在了,就返回常量池中的引用。
//True False
public static void main(String[] args) {
String str1=new StringBuilder("java").append("虚拟机").toString();//执行完这行代码后,常量池中会有"java"和"虚拟机",但是不会有"java虚拟机"。
System.out.println(str1.intern()==str1);
String str2=new String("我喜欢java"); //执行完这行代码后,常量池中会有"我喜欢java"
System.out.println(str2==str2.intern());
}
可以通过反射打破这种不可变性。
public class Test {
public static void main(String[] args){
String str = "hello";
try {
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[])field.get(str);
value[2] = 'k';
}
catch (NoSuchFieldException e){
}
catch(IllegalAccessException e){
}
System.out.println(str); //heklo
}
}
3. List排序
//自然排序
ArrayList<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(1);
Collections.sort(list); //1,2,3
4. Java集合遍历
Java集合框架图如下所示:
![](https://img.haomeiwen.com/i17524543/67c9221484a72f73.gif)
4.1 普通for循环遍历
第一次删除2时,这个位置之后的所有元素都向前挪动一个位置,故索引值为2时对应的数值为4,可以手动设置i--恢复正常遍历顺序。使用list.set()方法可以修改列表元素,使用list.add()方法新增元素时会在list最后插入数据。
public class Test {
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
for(int i=0;i<list.size();i++){
if(list.get(i) == 2) {
list.remove(i);
// i--;
}
}
System.out.println(list); //[1, 2, 4, 5]
}
}
4.2 增强for循环遍历
在增强for循环里删除或者添加集合元素,会报java.util.ConcurrentModificationException异常信息。
![](https://img.haomeiwen.com/i17524543/1213142335965e5c.png)
public class Test {
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
for (Integer a: list) {
if (a == 2){
list.remove(a);
}
}
System.out.println(list);
}
}
增强for循环本质上是隐式的iterator,由于在删除和添加的时候会导致modCount发生变化,但是没有重新设置expectedModCount,当使用list.remove()后遍历执行iterator.next()时,方法检验modCount的值和的expectedModCount值,如果不相等,就会报ConcurrentModificationException。
![](https://img.haomeiwen.com/i17524543/95017e2b4fef4269.png)
4.3 迭代器遍历
使用list方法的add()方法和remove()方法,同样会报java.util.ConcurrentModificationException异常错误,原因同4.2。
public class Test {
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(2);
list.add(4);
list.add(5);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Integer a = iterator.next();
if (a == 2){
list.remove(a);
}
}
System.out.println(list);
}
}
使用迭代器的remove()方法,则不会报错。 list.iterator()返回的Itr对象的remove方法维护了modCount和expectedModCount值。
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Integer a = iterator.next();
if (a == 2){
iterator.remove();
}
}
Itr对象的remove方法源码如下所示:
public void remove() {
if (this.lastRet < 0) {
throw new IllegalStateException();
} else {
this.checkForComodification();
try {
ArrayList.this.remove(this.lastRet);
this.cursor = this.lastRet;
this.lastRet = -1;
this.expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException var2) {
throw new ConcurrentModificationException();
}
}
}
ListIterator类型的迭代器提供了add()方法和set()方法,支持List的新增和修改。
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()){
Integer a = iterator.next();
if (a == 2){
iterator.add(66);
}
}
//此时输出结果为[1, 2, 66, 2, 66, 4, 5]
4.4 foEach遍历(Jdk1.8新增)
list.forEach(Integer->System.out.println(Integer));
4.5 通过keyset()遍历Map
遍历时可通过map.put()方法修改,但是不能添加元素,否则会报java.util.ConcurrentModificationException异常错误。删除元素不会生效。
public class Test {
public static void main(String[] args){
HashMap<String,String> map = new HashMap<>();
map.put("1","hello");
map.put("2","world");
map.put("3","get");
for (String str:map.keySet()){
//可修改,不可删除和添加
System.out.println(map.get(str));
}
}
4.6 通过entrySet()方法遍历key和value
使用该方式效率最高。
for(Map.Entry<String,String> entry:map.entrySet()){
System.out.println(entry.getKey()+entry.getValue());
}
4.7 迭代遍历Map
Iterator<Map.Entry<String,String>> iteratorEntry = map.entrySet().iterator();
while (iteratorEntry.hasNext()){
Map.Entry<String,String> entry = iteratorEntry.next();
System.out.println(entry.getKey()+entry.getValue());
}
4.8 通过values()方法遍历Map所有的value
for (String value:map.values()){
System.out.println(value);
}
5. Java日志打印
Logger logger = LoggerFactory.getLogger(getClass());
logger.info("info message!");
6.List和数组互相转化
//数组转list-Arrays.asList
String[] strArray = {"hello", "world"};
List<String> list = Arrays.asList(strArray);
for (String str : list) {
System.out.println(str);
}
//list转数组-list.toArray
String[] newStrArray = new String[list.size()];
list.toArray(newStrArray);
for (String str:newStrArray){
System.out.println(str);
}
7. 生成随机数
//随机生成1-10的整数
Random random = new Random();
int num = random.nextInt(10)+1;
8. 四舍五入
//四舍五入
int roundNum = (int) Math.round(num);
//向上取整
int ceilNum = (int) Math.ceil(num);
//向下取整
int floorNum = (int) Math.floor(num);
9. Eclipse & IDEA常用快捷键
01)打开类型:Ctrl+Shift+T
02)打开资源:Ctrl+Shift+R
03)打开搜索对话框: Ctrl+H
04)删除行:Ctrl+D
05)组织导入:Ctrl+Shift+O
06)定位在某行:Ctrl+L
07)定位到最后编辑的地方:Ctrl+Q
08)Debug模式下可以直接看到变量的值:Ctrl+Shift+I
09)快速显示当前类的继承结构:Ctrl+T
10)快速Outline:Ctrl+O
11) 重命名:Alt+Shift+R
12)上下移动代码:Alt+↑或↓
13)Surround With:Ctrl+Alt+T
14)自动导入依赖:Alt+Enter
15)导入重写、构造方法:Alt+Ins
16)显式继承关系图:Ctrl+Alt+U
17)跳转项目:Ctrl+Alt+]
18)文件跳转:Ctrl+E
19)Find Action:Ctrl+Shift+A
20)添加书签:Ctrl+Shfit+F11
21)添加断点:Ctrl+Shift+B
22)条件断点:Ctrl+Shift+F8
23)变量分析:Ctrl+U
将IDEAD的快捷方式设置为Eclipse模式:file->settings->keymap (eclipse),如图6-1所示:
![](https://img.haomeiwen.com/i17524543/4af1750227ecdd8e.png)
设置IDEAD忽略重复代码:file->settings->editor->inspections(General-Duplicated Code),如图6-2所示:
![](https://img.haomeiwen.com/i17524543/bd989bf23355c0c1.png)
设置IDEAD类注释模版:file->settings->editor->file and code templates(Class),如图6-3所示:
![](https://img.haomeiwen.com/i17524543/4b5b36f9ceebbb20.png)
IDEAD切换GIT远程分支:项目->git->repository->pull,点击刷新,如图6-4所示:
![](https://img.haomeiwen.com/i17524543/443ad0c62f2a8e47.png)
参考资料:
1)Java-String类型的参数传递问题
2)Java中的String为什么是不可变的? -- String源码分析
3)Java集合——遍历集合元素并修改
------<未完待续>------
网友评论