目录
1. 常见JDK注解
- @Override:限定重写父类方法,该注解只能用于方法
- @Deprecated: 用于表示所修饰的元素(类或方法)已过时,通常是指该结构危险或存在更好的选择
- SuppressWarnings:抑制编译器警告
@Deprecated//过时注解
public String getName() {
return name;
}
@Override
public String toString() {
return "Children{}";
}
@SuppressWarnings("unused")
public static void main(String[] args) {
int i = 123;
Parent p = new Children();
p.f1();
p.f2();
}
2. JDK元注解
- @Target:指定注解可以应用的目标元素类型,如类、方法、字段等。
@Target({ElementType.FIELD, ElementType.METHOD})
能在字段和方法中使用 - @Retention:指定注解的生命周期,即注解在哪个阶段仍然可用,如源代码、编译时、运行时。
@Retention(RetentionPolicy.RUNTIME)
在运行时保留 - @Documented:指定该注解是否包含在生成的文档中。
- @Inherited:指定该注解是否可以被继承,默认情况下注解不会被子类继承。
- @Repeatable:指定该注解是否可以重复应用于同一目标元素。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyAnnotation {
String value() default "hello";
}
假设我们有一个自定义注解 @MyAnnotation,我们希望在同一个类的方法上可以重复应用该注解。
如果我们直接在一个方法上重复应用 @MyAnnotation,会产生编译错误。
但是,如果我们在 @MyAnnotation 的定义上添加了 @Repeatable(MyAnnotations.class) 注解,
则可以创建一个容器注解 @MyAnnotations 来容纳多个 @MyAnnotation 注解。
@Repeatable(MyAnnotations.class)
public @interface MyAnnotation {
// 定义注解的元素...
}
public @interface MyAnnotations {
MyAnnotation[] value();
}
// 在同一个目标元素上重复应用 @MyAnnotation
@MyAnnotation
@MyAnnotation
public void myMethod() {
// 方法体...
}
这些元注解可以与自定义注解一起使用,以控制注解的行为和约束。通过使用元注解,我们可以根据需要对注解进行更精确的配置,并使其更具可重用性和可扩展性
3. 自定义注解
import java.lang.annotation.*;
@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface MyAnnotation {
String value() default "hello";
}
public class Annotation_ {
@MyAnnotation("hello world")
private String name = "lei_li";
}
4. 集合框架概述
4.1 集合和数组的区别
数组的弊端
- 数组的大小不能改变
- 数组不便于进行添加、删除、插入等操作, 且效率不高。无法直接获取元素的个数
- 数组中的元素是有序的、可以重复的。 存储数据的特点单一
4.2 集合类关系图
简化图如下
5. Collection接口
- Collection 接口是 List、 Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
- JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如: Set和List)实现。
- 在 Java5 之前, Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理; 从 JDK 5.0 增加了泛型以后, Java 集合可以记住容器中对象的数据类型。
5.1 接口方法
- 添加
add(Object obj)
- 集合的合并
addAll(Collection coll)
- 获取元素个数
int size()
- 清空集合
void clear()
- 是否为空集合
boolean isEmpty()
- 是否包含某一个元素
boolean contains(Object obj)
默认比较地址,重写equals方法。boolean containsAll(Collection c)
两个集合的元素挨个比较 - 移除某个元素
boolean remove(Object obj)
默认移除最先找到的元素 - 遍历
iterator()
返回迭代器对象,用于集合遍历
public class Test1 {
@Test
public void test1() {
Collection c1 = new ArrayList();获取Collection对象
//添加元素
c1.add("Hello");
c1.add("World");
c1.add("Tom");
Person person1 = new Person("Tom", 28);
Person person2 = new Person("Tom", 28);
Person person3 = new Person("Tom", 28);
c1.add(person1);
c1.add(person2);
//删除元素
c1.remove("Hello");
//判断是否为空集合
System.out.println(c1.isEmpty());
//是否包含某个元素
System.out.println("比较内容是否相等=" + c1.contains(person3));
比较内容,调用equals方法,没有方法默认比较地址,这里重写了equals方法
System.out.println(c1);//输出所有元素
}
class Person {
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override 重写toString方法
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Person)) {
return false;
}
Person person = (Person) obj;
return this.name.equals(person.name) &&
this.age == person.age;
}
}
运行结果
false
比较内容是否相等=true
[World, Tom, Person{name='Tom', age=28}, Person{name='Tom', age=28}]
6. iterator迭代器接口
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
- hasnext() 如果有下一个元素,返回true
- next() 在迭代器中返回下一个元素
- remove() 移除某个元素
iterator循环集合并删除“Tom”
Iterator it = c.iterator();//获取iterator指针
while (it.hasNext()) {
Object obj = it.next();
//删除Tom
if ("Tom".equals(obj)) {
it.remove();
}
}
for增强循环,底层是Iterator循环iter
for (Object obj : c1) {
System.out.println(obj);
}
7. List接口
- List集合类中元素有序、且可重复、集合中的每个元素都都有对应的顺序索引
- 实现List接口的实现类有
ArrayList LinkedList Vector
7.1 List接口方法
void add(int index,Object obj)
在index位置插入obj元素Object get(int index)
获取index位置的元素int indexOf(Object obj)
获取obj元素首次出现的位置int lastIndexOf(Object obj)
获取obj元素最后出现的位置Object remove(int index)
移除指定位置的元素,并返回该元素Object set(int index, Object ele)
修改index位置的元素List subList(int fromIndex, int toIndex)
返回从fromIndex到toIndex位置的子集合
7.2 ArraryList
ArrayList 内部实现使用数组进行存储,扩容时会创建更大的数组空间,把原有数据复制到新数组中。
ArrayList 支持对元素的快速随机访问,但是插入与删除时速度通常很慢,因为这个过程很有可能需要移动其他元素。
- ArrayList 是 List 接口的典型实现类、主要实现类
- ArrayList的JDK1.8之前与之后的实现区别?
- JDK1.7: ArrayList像饿汉式,直接创建一个初始容量为10的数组
- JDK1.8: ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组,当元素个数超过数组容量时,扩容1.5倍。
7.3 LinkedList
LinkedList 的本质是双向链表。与 ArrayList 相比,LinkedList 的插入和删除速度更快,但是随机访问速度很慢。
除继承 AbstractList 抽象类外,LinkedList还实现了另一个接口 Deque ,即 double-ended queue。这个接口同时具有队列和枝的性质。
LinkedList 包含 3 个重要的成员 size 、first、 last 。 size 是双向链表中节点的个数。first 和 last 分别指向第一个和最后一个节点的引用。
LinkedList 的优点在于可以将零散的内存单元通过附加引用的方式关联起来,形成按链路顺序序查找的线性结构,内存利用率较高。
7.3.1 LinkedList新增的方法
● void addFirst(Object obj)
● void addLast(Object obj)
● Object getFirst()
● Object getLast()
● Object removeFirst()
● Object removeLast()
LinkedList:双向链表, 内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。 Node除了保存数据,还定义了两个变量:
● prev变量记录前一个元素的位置
● next变量记录下一个元素的位置
7.4 案例
//ArrayList创建方式
List list = new ArrayList();
//LinkedList创建方式
LinkedList list = new LinkedList();
四种循环打印方式
//1 直接打印
System.out.println(list);
//2.增强for
for (Object o : list) {
System.out.println(o);
}
//3.常规方式
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//4. 迭代器
Iterator iterator= list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
8.初始化面试题
为什么阿里规约规定使用集合要指定initialCapacity
减少内存空间的重新分配:当集合中的元素数量增加时,如果未指定初始容量,集合会根据自身策略进行动态扩容。这时,会发生内
部数组的重新分配和元素的复制,这个过程会消耗一定的时间和资源。通过指定初始容量,可以避免不必要的扩容操作,提高了性能。
List list = new ArrayList(20);