先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
正文
适配器方法惯用法
如果现有一个Iterable类
,你想要添加一种或多种在foreach
语句中使用这个类的方法,应该怎么做呢?例如,假设你希望可以选择以向前的方向或是向后的方向迭代一个单词列表。如果直接继承这个类,并覆盖iterator()
你只能替换现有的方法,而不能实现选择。 一种解决方案是所谓适配器方法的惯用法。“适配器”部分来自于设计模式,因为你必须提供特定接口以满足foreach
语句。当你有一个接口并需要另一个接口时,编写适配器就可以解决问题。这里,我希望在默认的前向迭代器的基础上,添加产生反向迭代器的能力,因此我不能使用覆盖,而是添加了一个能够产生Iterable
对象的方法,该对象可以用于foreach
语句。正如你所见,这使得我们可以提供多种使用foreach
的方式:
package p10;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class AdapterMethodIdiom{
public static void main(String[] args) {
ReversibleArrayList ral = new ReversibleArrayList<>(Arrays.asList(“To be or not to be”.split(" ")));
for(String s:ral){
System.out.print(s + " ");
}
System.out.println();
// Hand it the Iterable of your choice
for(String s : ral.reversed()){
System.out.print(s + " ");
}
/**
- To be or not to be
- be to not or be To
*/
}
}
class ReversibleArrayList extends ArrayList {
public ReversibleArrayList(Collection c){
super©;
}
public Iterable reversed(){
return new Iterable() {
@Override
public Iterator iterator() {
return new Iterator(){
int cursor = size() - 1;
@Override
public boolean hasNext() {
return cursor > -1;
}
@Override
public T next() {
return get(cursor–);
}
};
}
};
};
}
如果直接将ral对象置于foreach
语句中,将得到(默认的)前向迭代器。但是如果在该对象上调用reversed()方法
,就会产生不同的行为。 通过使用这种方式,我可以在IterableClass.java
示例中添加两种适配器方法:
package p10;
import java.util.*;
public class MultiIterableClass extends IterableClass{
public Iterable reversed(){
return new Iterable() {
@Override
public Iterator iterator() {
return new Iterator() {
int cursor = words.length - 1;
@Override
public boolean hasNext() {
return cursor > -1;
}
@Override
public String next() {
return words[cursor–];
}
};
}
};
}
public Iterable randomized(){
return new Iterable() {
@Override
public Iterator iterator() {
List shuffled = new ArrayList<>(Arrays.asList(words));
Collections.shuffle(shuffled,new Random(47));
return shuffled.iterator();
}
};
}
public static void main(String[] args) {
MultiIterableClass mic = new MultiIterableClass();
for(String s:mic.reversed()){
System.out.print(s + " ");
}
System.out.println();
for(String s:mic.randomized()){
System.out.print(s + " ");
}
System.out.println();
for(String s:mic){
System.out.print(s + " ");
}
/**
- banana-shaped. be to Earth the know we how is that And
- is banana-shaped. Earth that how the be And we know to
- And that is how we know the Earth to be banana-shaped.
*/
}
}
注意,第二个方法random()
没有创建它自己的Iterator
,而是直接返回被打乱的List中的Iterator
。 从输出中可以看到,Collection.shuffe()
方法没有影响到原来的数组,而只是打乱了shuffied
中的引用。之所以这样,只是因为randomized()方法
用一个ArrayList
将Arrays.asList()
方法的结果包装了起来。如果这个由Arrays.asList()
方法产生的List被直接打乱,那么它就会修改底层的数组,就像下面这样:
package p10;
import java.util.*;
public class ModifyingArraysAsList {
public static void main(String[] args) {
Random random = new Random(47);
Integer[] ia = {1,2,3,4,5,6,7,8,9,10};
List list1 = new ArrayList<>(Arrays.asList(ia));
System.out.println("Before shuffling: " + list1);
Collections.shuffle(list1,random);
System.out.println("After shuffling: " + list1);
System.out.println("array: " + Arrays.toString(ia));
List list2 = Arrays.asList(ia);
System.out.println("Before shuffling: " + list2);
Collections.shuffle(list2,random);
System.out.println("After shuffling: " + list2);
System.out.println("array: " + Arrays.toString(ia));
/**
- Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9]
- array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- After shuffling: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
- array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
*/
}
}
在第一种情况中,Arrays.asList()
的输出被传递给了ArrayList()
的构造器,这将创建一个引用ia的元素的ArrayList
,因此打乱这些引用不会修改该数组。但是,如果直接使用Arrays.asList(ia)
的结果,这种打乱就会修改ia的顺序。意识到Arrays.asList()
产生的List对象会使用底层数组作为其物理实现是很重要的。只要你执行的操作会修改这个List,并且你不想原来的数组被修改,那么你就应该在另一个容器中创建一个副本。
最后
学习视频:
大厂面试真题:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-WXtxuyDz-1713382612014)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!