1.SparseArrayhtml
当新建一个key为整型的HashMap时,会出现以下的提示信息,推荐使用SparseArray来替代HashMap: java
![]()
接下来就来介绍下SparseArray:程序员
a.数据结构:又称稀疏数组,内部经过两个数组分别存储key和value,并用压缩的方式来存储数据后端
b.优势:可替代key为int、value为Object的HashMap,相比于HashMap数组
c.适用场景:数据量不大(千之内)、空间比时间重要、须要使用Map且key为整型;不适合存储大容量数据,此时性能将退化至少50%安全
d.使用服务器
public void put(int key, E value)
public void delete(int key)
public void remove(int key)
实际上内部会调用delete方法public E get(int key)
public E get(int key, E valueIfKeyNotFound)
可设置假设key不存在时默认返回的valuepublic int keyAt(int index)
获取相应的keypublic E valueAt(int index)
获取相应的valuee.get/put过程:元素会按照key从小到大进行存储,先使用二分法查询key对应在数组中的下标index,而后经过该index进行增删查。源码分析见SparseArray解析数据结构
2.atomic包多线程
a.原子操做类:与采起悲观锁策略的synchronized不一样,atomic包采用乐观锁策略去原子更新数据,并使用CAS技术具体实现并发
//保证自增线程安全的两种方式
public class Sample {
private static Integer count = 0;
synchronized public static void increment() {
count++;
}
}
public class Sample {
private static AtomicInteger count = new AtomicInteger(0);
public static void increment() {
count.getAndIncrement();
}
}
复制代码
b.类型
原子更新基本类型:
以AtomicInteger为例,经常使用方法:
getAndAdd(int delta)
:取当前值,再和delta值相加addAndGet(int delta)
:先和delta值相加,再取相加后的最终值getAndIncrement()
:取当前 值,再自增incrementAndGet()
:先自增,再取自增后的最终值getAndSet(int newValue)
:取当前值,再设置为newValue值
原子更新数组:
以AtomicIntegerArray为例,经常使用方法:
addAndGet(int i, int delta)
:先将数组中索引为i的元素与delta值相加,再取相加后的最终值getAndIncrement(int i)
:取数组中索引为i的元素的值,再自增compareAndSet(int i, int expect, int update)
:若是数组中索引为i的元素的值和expect值相等,则更新为update值
原子更新引用类型:
//这几个类提供的方法基本一致,以AtomicReference为例
public class AtomicDemo {
private static AtomicReference<User> reference = new AtomicReference<>();
public static void main(String[] args) {
User user1 = new User("a", 1);
reference.set(user1);
User user2 = new User("b",2);
User user = reference.getAndSet(user2);
System.out.println(user);//输出User{userName='a', age=1}
System.out.println(reference.get());//输出User{userName='b', age=2}
}
static class User {
private String userName;
private int age;
public User(String userName, int age) {
this.userName = userName;
this.age = age;
}
@Override
public String toString() {
return "User{" +"userName='" + userName + '\'' +", age=" + age + '}';
}
}
}
复制代码
原子更新字段:
使用方法:因为原子更新字段类是抽象类,所以须要先经过其静态方法
newUpdater
建立一个更新器,并设置想更新的类和属性 注意:被更新的属性必须用public volatile
修饰
//这几个类提供的方法基本一致,以AtomicIntegeFieldUpdater为例
public class AtomicDemo {
private static AtomicIntegerFieldUpdater updater = AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
public static void main(String[] args) {
User user = new User("a", 1);
int oldValue = updater.getAndAdd(user, 5);
System.out.println(oldValue);//输出1
System.out.println(updater.get(user));//输出6
}
static class User {
private String userName;
public volatile int age;
public User(String userName, int age) {
this.userName = userName;
this.age = age;
}
@Override
public String toString() {
return "User{" +"userName='" + userName + '\'' +", age=" + age +'}';
}
}
}
复制代码
c.优势:能够避免多线程的优先级倒置和死锁状况的发生,提高在高并发处理下的性能,相比于synchronized ,在非激烈竞争的状况下,开销更小,速度更快
3.Android埋点
a.含义:预先在目标应用采集数据,对特定用户行为或事件进行捕获、处理,并以必定方式上报至服务器,便于后续进行数据分析
b.方式
4.Java基础之注解(Annotation)
a.含义:是附加在代码中的一些元数据,在JDK1.5 版本开始引入,与类、接口、枚举在同一个层次
b.做用:
c.使用
如下代码展现了注解的定义、属性和使用的方法:
//1.注解的定义:经过@interface关键字
//如下表示建立了一个名为TestAnnotation的注解
public @interface TestAnnotation {
//2.注解的属性:
//声明:采用“无形参的方法”形式,方法名表示属性名,返回值表示属性类型
//类型:必须是8种基本数据类型,或者类、接口、注解及对应数组
//默认值:用default关键值,在赋值时能够省略
//如下表示注解TestAnnotation中有id和msg两个属性,且msg默认值为hi
int id();
String msg() default "hi";
}
//3.注解的使用:
//对属性赋值:在注解使用打个括号,以value=""形式,多个属性以前用逗号隔开;若注解只有一个属性,则赋值时value=能够省略;若是没有属性,括号均可以省略
//如下表示对Test类进行标识,并对注解的适两个属性进行赋值
@TestAnnotation(id=1,msg="hello")
public class Test {
}
复制代码
d.类型:
名称 | 做用 | 取值 |
---|---|---|
@Target (目标注解) |
描述注解的限定使用范围 | ElementType.CONSTRUCTOR : 对构造方法进行注解;ElementType.ANNOTATION_TYPE : 对注解进行注解;ElementType.FIELD : 对属性进行注解;ElementType.LOCAL_VARIABLE : 对局部变量进行注解;ElementType.METHOD : 对方法进行注解;ElementType.PACKAGE : 对包进行注解;ElementType.PARAMETER : 对描述参数进行注解;ElementType.TYPE : 对类型(类、接口、枚举)进行注解 |
@Inherited (继承注解) |
拥有该注解的注解所做用的类,且其子类未带任何注解,则该子类也会继承父类的注解 | |
@Retention (保留注解) |
描述注解的生命周期 | RetentionPolicy.SOURCE : 注解只保留在源码阶段,在编译器完整编译以后会被丢弃忽视;RetentionPolicy.CLASS : 注解会保留到编译进行时,但不会被加载到 JVM ;RetentionPolicy.RUNTIME : 注解会保留到程序运行时,且会被加载进入到 JVM |
@Documented (文档注解) |
将注解添加到Java文档 | |
@Repeatable (可重复注解) |
表示注解的值能够同时取多个 |
来段代码感觉下这些注释的使用效果:
//表示TestAnnotation注释是对类描述的、保留到运行时、被添加到Javadoc、有继承性值的
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TestAnnotation {
}
//因为B类是A类的子类,且B类没被任何注解应用,则B类继承了A类的TestAnnotation注解
@TestAnnotation
public class A {}
public class B extends A {}
复制代码
接下来用单独一个例子来解释可重复注解
//1.定义一个注解容器(此处指@Persons):
//做用:存放其余注解(此处指@Person),其自己也是个注解
//注意:须要有个value属性,类型就是被@Repeatable解释的注解数组(此处指Person[])
@interface Persons {
Person[] value();//注解属性
}
//2.使用@Repeatable解释(此处指@Person),括号中是注解容器类(此处指Persons)
@Repeatable(Persons.class)
@interface Person {
String role default "";//注解属性
}
//3.使用@Repeatable解释的注释时,能够取多个注解值来解释代码
@Person(role="coder")
@Person(role="PM")
public class SuperMan {//SuperMan既是程序员又是产品经理
}
复制代码
名称 | 做用 |
---|---|
@Override (复写注解) |
被标记的方法须要被子类复写,不然编译器会报错 |
@Deprecated (过期注解) |
标记已过期的元素,当元素使用时会在代码划横线 |
@SuppressWarnings (阻止警告注解) |
被标记的元素会阻止编译器发出警告提醒 |
@SafeVarargs (参数安全类型注解) |
提醒开发者不要用参数作不安全的操做、阻止编译器产生unchecked警告 |
方法名 | 返回值 | 描述 |
---|---|---|
isAnnotationPresent(Class<? extends Annotation> annotationClass) |
boolean |
若是指定类型的注解存在于此元素上,则返回 true,不然返回 false |
getAnnotation(Class<A> annotationClass) |
<A extends Annotation> |
该元素若是存在指定类型的注解,则返回这些注解,不然返回 null |
getAnnotations() |
Annotation[] |
返回此元素上存在的全部注解,包括从父类继承的 |
getDeclaredAnnotations() |
Annotation[] |
返回直接存在于此元素上的全部注解,但不包括父类的注解 |
在以前的Test类里就能够添加如下代码,来获取在类上给@TestAnnotation设置的属性值了:
boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
if (hasAnnotation) {
TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
System.out.println("id:"+testAnnotation.id());//输出1
System.out.println("msg:"+testAnnotation.msg());//输出hello
}
复制代码
推荐阅读:秒懂,Java 注解 (Annotation)你能够这样学
5.一点小感悟
最近的生活变得很是规律和健康,果真工做令人勤快,从早上出门开始,穿梭巴士、免费早餐、养生茶水、一餐一果、关灯午休、夜宵券、打车报销...天天都能感觉到鹅厂对员工的关怀,幸福感满满。
这阵子的工做也有了新的进展,走过了熟悉项目、定位bug、讨论方案的阶段,写下了第一行代码~捋代码逻辑的这段日子我开始深深怀疑人生,感受智商down到谷底,这里就不得不感激导师的耐心指导,还老是关心我有没有疑问,努力挽救一个辣鸡少女。
前几天开了个总结会,关于某个版本的bug review,不只是回顾bug产生缘由和解决办法,更可能是反思和总结经验,好比反复打补丁不如从根源解决、重构务必看懂每行代码切勿放过哪怕一个字段、注意空指针问题、要考虑到边界条件、自测要到位、多机型多系统测试、使用接口要注意内部实现...听罢感受受益不浅,提醒本身时刻注意,少走些弯路。
看着同事愈来愈少才发觉立刻就放假了,不过你们都丝毫没有懈怠,天天十点多还没什么人离开,有时候大半夜还在群里讨论方案,周五也是如此,周末有天来公司还看到几个好学的小哥哥在,和优秀的人共事也但愿本身早日也能如此优秀呀~
PS:上周末由于身体不舒服没有及时更新,和这周就合并了~还有立刻过年了提早祝你们新年快乐,假期愉快,明年再见(`・ω・´)