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);
*/
Effective Java学习
用静态工厂方法代替构造器:
优点:
- 有名称
- 不用每次创建都新建一个对象
- 返回原返回类型的任何子类对象
- 返回对象的类可以随着每次调用发生变化
- 方法返回对象所属的类,在编写该静态方法时,可以不存在
缺点:
- 类如果不包含公有的或者受保护的构造起,就不能被子类化
- 程序员很难发现他们
内存溢出:Out of Memory (OOM) 理解起来也很简单,就是内存不够用了。
内存泄漏:Memory Leak 通常是由于错误或失误,从一个开口进入或逃脱。由于程序的编写错误暴漏出一些 开口,导致一些对象进入这写开口,最终导致相关问题,进一步说白了,程序有漏洞,不当的调用就会出问题。
什么是内存泄漏?
堆中存在一些不再使用的对象,但垃圾收集器无法将它们从内存中删除(垃圾收集器定期删除未引用的对象,但从不收集仍在引用的对象),因此对它们进行了不必要的维护;如果有用的、但垃圾收集器又不能删除的对象增多,那么就会逐渐导致内存溢出(OOM)了。
内存泄漏带来的问题:
- 当应用程序长时间连续运行时,性能会严重下降,毕竟可用内存变小
- 自发的和奇怪的应用程序崩溃
- 应用程序偶尔会耗尽连接对象
- 最终的结果是 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);
学习Spring Boot Starter