Skip to content

Latest commit

 

History

History
157 lines (116 loc) · 4.62 KB

20200807.md

File metadata and controls

157 lines (116 loc) · 4.62 KB

Algorithm

303. Range Sum Query - Immutable

Description:

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

Constraints:

  • You may assume that the array does not change.
  • There are many calls to sumRange function.
  • 0 <= nums.length <= 10^4
  • -10^5 <= nums[i] <= 10^5
  • 0 <= i <= j < nums.length

Solution:

class NumArray {

    // 用来存放累加和
    private int[] sum;

    // 构造函数初始化sum
    public NumArray(int[] nums) {
        sum = nums;
        for(int i=0;i<nums.length;i++){
           sum[i] = sum[i-1] + nums[i];
        }
    }

    // 每次返回sum[j] - sum[i-1] 注意边界
    public int sumRange(int i, int j) {
        if(i<0 || j>sum.length || i>j){
           return 0;
        }
        if(i==0){
           return sum[i];
        }else{
           return sum[j] - sum[i-1];
        }
    }
}
/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(i,j);
 */

Review

Effective Java学习

用静态工厂方法代替构造器:

优点:

  1. 有名称
  2. 不用每次创建都新建一个对象
  3. 返回原返回类型的任何子类对象
  4. 返回对象的类可以随着每次调用发生变化
  5. 方法返回对象所属的类,在编写该静态方法时,可以不存在

缺点:

  1. 类如果不包含公有的或者受保护的构造起,就不能被子类化
  2. 程序员很难发现他们

Tip

内存溢出:Out of Memory (OOM) 理解起来也很简单,就是内存不够用了。

内存泄漏:Memory Leak 通常是由于错误或失误,从一个开口进入或逃脱。由于程序的编写错误暴漏出一些 开口,导致一些对象进入这写开口,最终导致相关问题,进一步说白了,程序有漏洞,不当的调用就会出问题。

什么是内存泄漏?

堆中存在一些不再使用的对象,但垃圾收集器无法将它们从内存中删除(垃圾收集器定期删除未引用的对象,但从不收集仍在引用的对象),因此对它们进行了不必要的维护;如果有用的、但垃圾收集器又不能删除的对象增多,那么就会逐渐导致内存溢出(OOM)了。

内存泄漏带来的问题:

  1. 当应用程序长时间连续运行时,性能会严重下降,毕竟可用内存变小
  2. 自发的和奇怪的应用程序崩溃
  3. 应用程序偶尔会耗尽连接对象
  4. 最终的结果是 OOM

常见的问题:

静态成员变量的乱用

@Slf4j
public class StaticTest {
 public static List<Double> list = new ArrayList<>();

 public void populateList() {
  for (int i = 0; i < 10000000; i++) {
   list.add(Math.random());
  }
 }

 public static void main(String[] args) {
  new StaticTest().populateList();
 }
}

populateList() 是一个 public 方法,可能被各种调用,导致 list 无限增大 解决办法:

解决办法很简单,针对这种情形(也就是通常所说的长周期对象引用短周期对象),就是将 list 放到方法内部,方法栈帧执行完自动就会被回收了

public void populateList() {
   List<Double> list = new ArrayList<>();
   for (int i = 0; i < 10000000; i++) {
      list.add(Math.random());
   }
}

Spring 源码时有好多是 static 修饰的成员变量, 它们都是是在容器初始化的过程中一次性加载的,所以不会像 populateList 随着调用次数的增加,无限撑大 List

未关闭的流

因为每当我们建立一个新的连接或打开一个流时(比如数据库连接、输入流和会话对象),JVM都会为这些资源分配内存,如果不关闭,这就是占用空间"有用"的对象, GC 就不会回收他们,当请求很大,来个请求就新建一个流,最终都还没关闭,结果可想而知

解决办法:

流的解决办法很简单,其实主要遵循相应范式就可以避免此类问题

  1. 通过 try/catch/finally范式在 finally 关掉流
  2. 如果你用的 Java 7+ 的版本,也可以用 try-with-resources, 这样代码在编译后会自动帮你关闭流
  3. 也可以使用 Lombok 的 @Cleanup 注解, 就像下面这样
@Cleanup InputStream jobJarInputStream = new URL(jobJarUrl).openStream();
@Cleanup OutputStream jobJarOutputStream = new FileOutputStream(jobJarFile);
IOUtils.copy(jobJarInputStream, jobJarOutputStream);

明天见

Share

学习Spring Boot Starter

https://github.com/guangxush/SpringBoot_Starter