Java开发总结整理一

一、Integer等包装类要使用equals进行对比,否则会有问题。
public class HelloWorld {
    public static void main(String[] args) {
        Integer a=150;
        Integer b=150;
        Integer c = new Integer(20);
        System.out.println(a==b);//false
        System.out.println(a.equals(b));//true
    }
}
二、List等列表遍历时移除要采用以下:
推荐做法:
Iterator<Integer> integerIterator = integerList.listIterator();
while(integerIterator.hasNext()){
    Integer eachInteger = integerIterator.next();
    if(eachInteger.equals(removeInteger)){
        integerIterator.remove();
    }
}
错误做法,会导致java.util.ConcurrentModificationException异常。代码如下:
for(Integer eachInteger:integerList){
    if(eachInteger.equals(removeInteger)){
        integerList.remove(eachInteger);
    }
}
三、equals和hashCode

equals()和 hashcode()是java.lang.Object中提供的用以对象比较的两个重要方法,下面是其定义及默认实现:
public boolean equals(Object obj) {return (this == obj);}
用以判断变量参数与当前实例是否相等,JDK默认实现是基于对象内存地址是否相同,如果两个对象内存地址相同,则表示两个对象相同。
public native int hashCode(); 
默认情况下,该方法返回一个随机整数,对于每个对象来说该数字唯一,但该数字并非恒定,可能随着程序的执行发生变化。
但是这一性质并不符合场景,比如一个不允许有重复值的对象数组/LIST(CONTAINS方法)。通过重写可以实现。
Jdk的api建议:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,
该协定声明相等对象必须具有相等的哈希码。
class Person{
    private String name;
    private Integer age;
    @Override
    public boolean equals(Object obj) {
        if(obj == this) return true;
        if(obj == null) return false;
        if(getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        return name.equals(other.name) && age.equals(other.age);
    }
    @Override
    public int hashCode() {
        String id = this.name + this.age + "";
        return id.hashCode();
    }
}

四、AtomicInteger原子操作类

1.为什么需要AtomicInteger原子操作类?
对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。
num++解析为num=num+1,明显,这个操作不具备原子性,多线程并发共享这个变量时必然会出现问题。
测试代码如下:
public class AtomicIntegerTest {
    private static final int THREADS_CONUT = 10;
    public static volatile int count = 0;
    public static void increase() { count++; }
    public static void main(String[] args) {
        Thread[] threads = new Thread[THREADS_CONUT];
        for (int i = 0; i < THREADS_CONUT; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        increase();
                    }
                }
            });
            threads[i].start();
        }
    //当有活动线程时,不往下执行
        while (Thread.activeCount() > 1) {Thread.yield();}
        System.out.println(count);
    }
}
每个线程对count变量进行1000此自增操作,实际结果却发现每次运行的结果都不相同。

2.要是换成volatile修饰count变量呢?

volatile关键字很重要的两个特性:
保证变量在线程间可见,对volatile变量所有的写操作都能立即反应到其他线程中,换句话说,volatile变量在各个线程中是一致的;
禁止指令的重排序优化;
经过测试数字仍然不正确,因为核心点在于java里的运算(比如自增)并不是原子性的。

3.用了AtomicInteger类后会变成什么样子呢?
public class AtomicIntegerTest {
    private static final int THREADS_CONUT = 10;
    public static AtomicInteger count = new AtomicInteger(0);
    public static void increase() { count.incrementAndGet(); }
    public static void main(String[] args) {
        Thread[] threads = new Thread[THREADS_CONUT];
        for (int i = 0; i < THREADS_CONUT; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        increase();
                    }
                }
            });
            threads[i].start();
        }
        while (Thread.activeCount() > 1) {Thread.yield();}
        System.out.println(count);
    }
}
结果每次都输出20000,程序输出了正确的结果,这都归功于AtomicInteger.incrementAndGet()方法的原子性。

五.TreeSet的使用
TreeSet集合:可以对Set集合中的元素进行排序。要求传入TreeSet的元素/对象实现了Comparable接口
class Person implements Comparable<Person>{
    private String name;
    private Integer age;
    public int compareTo(Person o) {
        Person p = (Person)o;
        return age.compareTo(p.age);
    }
}

java.util.TreeSet.pollFirst()用于检索和删除最小(第一个)元素。

六、ReentrantLock
相比Synchronized,ReentrantLock类提供了一些高级功能,主要有以下3项:
1.等待可中断,持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,这相当于Synchronized来说可以避免出现死锁的情况。
通过lock.lockInterruptibly()来实现这个机制。
2.公平锁,多个线程等待同一个锁时,必须按照申请锁的时间顺序获得锁,Synchronized锁非公平锁,
ReentrantLock默认的构造函数是创建的非公平锁,可以通过参数true设为公平锁,但公平锁表现的性能不是很好。
3.锁绑定多个条件,一个ReentrantLock对象可以同时绑定对个对象。ReenTrantLock提供了一个Condition(条件)类,
用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

六.创建新线程
Thread prodRaceThread = new Thread(new Runnable(){
    public void run(){
        try {
        executeService.doProdRaceSales(prsThread);
    } catch (Exception e) {
        prsThread.setCalStatus(Constants.PRODRACE_CALSTATUS_HANDLEFAIL);
        prodRaceSalesDao.updateProdRaceSales(prsThread);
        LOGGER.error("竞赛计算失败", e);
    }
    }
},"FeeRecal-Batch");
prodRaceThread.start();

七.循环调用代码
public void getAllDependFailTask(List<Task> taskList, Task failTask, Set<Task> dependTasklist) {
Integer failTaskId = failTask.getId();
List<Task> checkList = taskList.stream().filter(t -> t.getDepsId().contains(String.valueOf(failTaskId))).collect(Collectors.toList());
dependTasklist.addAll(checkList);
checkList.stream().forEach(t -> getAllDependFailTask(taskList,t,dependTasklist));
}

八.ENUM枚举
package Enum;
public class EnumTest1 {
    //常量定义(字符串)
    enum WeekDay {SUN, MON, TUE, WED, THT, FRI, SAT}
    //枚举接口
    public interface Behaviour {String getColour();}
    enum ColorEnum implements Behaviour{
        RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
        // 成员变量
        private String name;
        private int index;
        // 构造方法
        private ColorEnum(String name, int index) {this.name = name;this.index = index;}
        // 普通方法
        public static String getName(int index) {
            for (ColorEnum c : ColorEnum.values()) {
                if (c.getIndex() == index) {
                    return c.name;
                }
            }            return null;
        }
        // get set 方法
        public String getName() {return name;}
        public void setName(String name) {this.name = name;}
        public int getIndex() {return index;}
        public void setIndex(int index) {this.index = index;}
        @Override
        public String toString() {return this.index+"_"+this.name;}
        public String getColour() {return this.name;}
    }
    public static void main(String args[]){
        System.out.print(WeekDay.FRI+"\n");
        System.out.print("Week每一天:");
        for (WeekDay c : WeekDay.values()){
            System.out.print(c+",");
        }
        System.out.println("RED:"+ColorEnum.RED.getName());
        System.out.println("RED:"+ColorEnum.RED.getColour());
    }
}
九.Springboot注解等
@SpringBootApplication
通常用在主类上, 包含@Configuration、@EnableAutoConfiguration、@ComponentScan

@RestController
用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody

@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
该注解有六个属性:
params:指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
value:指定请求的实际地址,指定的地址可以是URI Template 模式
method:指定请求的method类型, GET、POST、PUT、DELETE等
consumes:指定处理请求的提交内容类型(Content-Type),如application/json,text/html;
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

@ResponseBody
表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析
为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。

@RequestBody
允许request的参数在request体中,而不是在直接连接的地址后面。(放在参数前)

@RequestParam
是来自HTTP请求体或请求url的QueryString中。

十.Java8新特性
1.Optional
Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常
import java.util.Optional;
class Person{
    private String name;
    public String getName() {return name;}
    public Person(String name){this.name = name;}
}
public class OptionalTest {
    public static void main(String args[]) throws Exception {
        OptionalTest java8Tester = new OptionalTest();
        Integer value1 = null;
        Integer value2 = new Integer(10);
        // Optional.ofNullable - 允许传递为 null 参数
        Optional<Integer> a = Optional.ofNullable(value1);
        // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
        Optional<Integer> b = Optional.of(value2);
        System.out.println(java8Tester.sum(a, b));
        //Optional.ofNullable.orElseThrow 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
        Integer c = Optional.ofNullable(value1).orElseThrow(() -> new Exception("当前对象为空!"));
        //Optional.map 若有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
        String d = a.map(a1 -> String.valueOf(a1)).orElse(null);
        Person p = new Person("小明");
        Optional<String> pName1 = Optional.ofNullable(p).map(Person::getName);
        String pName = Optional.ofNullable(p).map(Person::getName).orElse("");
    }

    public Integer sum(Optional<Integer> a, Optional<Integer> b) {
        // Optional.isPresent - 判断值是否存在
        System.out.println("第一个参数值存在: " + a.isPresent());
        System.out.println("第二个参数值存在: " + b.isPresent());
        // Optional.orElse - 如果值存在,返回它,否则返回默认值
        Integer value1 = a.orElse(new Integer(0));
        //Optional.get - 获取值,值需要存在
        Integer value2 = b.get();
        return value1 + value2;
    }
}

Lambda表达式
Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中), 使用Lambda表达式可以使代码变的更加简洁紧凑。  
示例:  
// Java 8之前:  
new Thread(new Runnable() {  
    @Override  
    public void run() {  
        System.out.println("Before Java8, too much code for too little to do");  
    }  
}).start();  
  
//Java 8方式:  
new Thread(()-> System.out.println("Before Java8, too much code for too little to do")).start();  
  
lambda 表达式的语法格式如下:  
() -> {}()  
Lambda语法解析:  
括号就是接口方法的括号,接口方法如果有参数,也需要写参数。只有一个参数时, 括号可以省略。  
-> : 分割左右部分的, 没啥好讲的。  
{} : 要实现的方法体。只有一行代码时, 可以不加括号, 可以不写return。  
注意:Lambda表达式要求首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。  
  
Lambda表达式简单例子:  
// 1. 不需要参数,返回值为 5    
() -> 5    
    
// 2. 接收一个参数(数字类型),返回其2倍的值    
x -> 2 * x    
    
// 3. 接受2个参数(数字),并返回他们的差值    
(x, y) -> x – y    
    
// 4. 接收2个int型整数,返回他们的和    
(int x, int y) -> x + y    
    
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)    
(String s) -> System.out.print(s)  
  
代码示例:  
package com.erayt;  
public class Java8Tester {  
    interface MathOperation {  
        int operation(int a, int b);  
    }  
  
    interface GreetingService {  
        void sayMessage(String message);  
    }  
  
    public static void main(String args[]){  
        Java8Tester tester = new Java8Tester();  
        // 类型声明  
        MathOperation addition = (int a,int b) -> a + b;  
        // 不用类型声明  
        MathOperation subtraction = (a, b) -> a - b;  
        // 大括号中的返回语句  
        MathOperation multiplication = (int a, int b) -> { return a * b; };  
        // 没有大括号及返回语句  
        MathOperation division = (int a, int b) -> a / b;  
        System.out.println("10 + 5 = " + tester.operate(10, 5, addition));  
        System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));  
        System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));  
        System.out.println("10 / 5 = " + tester.operate(10, 5, division));  
  
        // 不用括号  
        GreetingService greetService1 = message1 -> System.out.println("Hello " + message1);  
        // 用括号  
        GreetingService greetService2 = (message2) -> System.out.println("Hello " + message2);  
        greetService1.sayMessage("Runoob");  
        greetService2.sayMessage("Google");  
    }  
  
    private int operate(int a, int b, MathOperation mathOperation){  
        return mathOperation.operation(a, b);  
    }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值