Java集合框架实用指南

1.选择正确的collection/map

请参照此图正确的使用集合


在选择正确的collection/map之前,您可以参考这些问题。
  • 我需要排序吗?
  • 我会有空的键/值?DUPS?
  • 它会支持多个线程访问吗?
  • 我需要使用键/值对吗?
  • 我需要随机访问吗?
  • 它允许按索引访问元素吗?
  • 它提供快速添加和快速移除元素吗?


2.使用接口,而不是他的实现类作为类型

1.始终使用接口类型作为类型。

例如, 使用 List, Set, Map 等接口作为引用类型

// Better
List<String> list = new ArrayList<>(); 

// Avoid
ArrayList<String> list = new ArrayList<>();

// Better
Set<String> set = new HashSet<>();

//Avoid
HashSet<String> employees = new HashSet<>();

// Better
Map<String,String> map = new HashMap<>();

//Avoid
HashMap<String,String> map = new HashMap<>();

通过使用接口类型声明集合,代码将更加灵活,因为你可以在需要时轻松更改具体实现,例如:

List < String > list =  new  LinkedList <>();

当你的代码设计为依赖于List接口时,你可以轻松地在List的实现之间进行交换,而无需修改使用它的代码。

2.始终使用接口类型作为返回类型

例如

public Collection listEmployees() {
    List<Employee> employees = new ArrayList<>();
    // add Employees to the list
    return employees;
}
3.始终使用接口类型作为方法参数
public  void foo(Set < Integer > numbers){
}

在方法有参数的情况下,使用接口作为参数类型会更加的灵活。

3.使用通用类型和泛型操作符

// Avoid
List<Student> listStudents = new ArrayList<Student>();

// Better
List<Student> listStudents = new ArrayList<>();

// Avoid
Map<Integer, Map<String, Student>> map = new HashMap<Integer, Map<String, Student>>();

//Better
Map<Integer, Map<String, Student>> map = new HashMap<>();

4.集合判空首选isEmpty(),少用size()

避免这种方法判断集合是否为空:
if (listOfEmployees.size() > 0) {
    // dos something if the list is not empty  
}

相反,你应该使用isEmpty()方法:

if (!listOfEmployees.isEmpty()) {
    // dos something if the list is not empty
}

isEmpty()和size()之间没有性能差异。这是为了增强代码的可读性。

5.不要在返回集合的方法中返回null

如果一个方法被设计为返回一个集合,那么在集合中没有元素的情况下它不应该返回null。考虑以下方法:

public List<Student> findStudents(String className) {
    List<Student> listStudents = null;
 
    if (//students are found//) {
        // add students to the lsit
    }
 
    return listStudents;
}

在这里,如果找不到学生,该方法返回null。这里的关键点是,不应使用空值来表示没有结果。最好的做法是,返回一个空集合来表示没有结果。上述代码可以通过初始化集合来轻松更正:

List<Student> listStudents = new ArrayList<>;
  or 
Collections.empty();

因此,请始终检查代码的逻辑,返回一个空的集合,而不是null。

6.不要使用经典的for循环

如果你编写代码来迭代像下面这样的列表集合,并没有什么不妥:

for (int i = 0; i < listStudents.size(); i++) {
    Student aStudent = listStudents.get(i);
 
    // do something with aStudent
}

但是,这并不是好的做法,因为如果在循环内某处改变,使用计数器变量I可能会导致潜在的错误。此外,这种循环不是面向对象的,因为每个集合都有自己的迭代器。因此建议使用类似以下代码的迭代器:

Iterator<Student> iterator = listStudents.iterator();
 
while (iterator.hasNext()) {
    Student nextStudent = iterator.next();
 
    // do something with next student
}
另外,如果迭代器创建后由另一个线程修改了集合,则该迭代器可能会抛出ConcurrentModificationException异常,这消除了潜在的错误。
现在,最好使用这样的增强for循环:
for (Student aStudent : listStudents) {
    // do something with aStudent
}

正如你所看到的,因为增强型for循环在后台使用迭代器,所以更简洁易读。

7.推荐使用forEach()和Lambda表达式

从Java 8开始,每个集合都提供了将迭代代码封装在集合本身内部的forEach()方法(内部迭代),并且您只需将Lambda表达式传递给此方法即可。这使得迭代代码更加紧凑,更灵活,更强大。下面一个例子:

List<String> fruits = Arrays.asList("Banana", "Lemon", "Orange", "Apple");
 
fruits.forEach(fruit -> System.out.println(fruit));

这相当于以下增强的for循环:

for(String fruit : fruits){
     System 。出去。的println(果实);
}

因此,我鼓励你使用该  forEach() 方法迭代集合,以帮助您专注于代码,而不是迭代。

8.正确的覆盖equals()和hashCode()方法

你必须在每个重写equals()的类里面重写hashCode()方法如果不这样做将导致违反Object.hashCode()的常规约定这将阻止 你的类与所有基于散列的集合(hash-based collections)(包括HashMap,HashSet和Hashtable)一起正常运行。

9.正确实现Comparable接口

请记住,Comparable 这个接口,当你自定义类型的元素被添加到按自然顺序排序元素的集合中时,你的自定义类型会实现该接口,例如  TreeSet 和  TreeMap它还有助于根据元素的自然排序对列表集合中的元素进行排序。

10.使用数组和集合时,使用实用程序类(utility classes)

请注意,Java集合框架提供了两个实用程序类  Arrays ,  Collections它们为我们提供了许多有用的功能。例如,  Arrays.asList() 方法返回包含给定元素的列表集合,如你所见,我在许多示例中使用了此方法:

List<String> listFruits = Arrays.asList("Apple", "Banana", "Orange");
List<Integer> listIntegers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Double> listDoubles = Arrays.asList(0.1, 1.2, 2.3, 3.4);

Collections类提供了各种有用的方法来  搜索,排序,修改 集合中的元素(几乎在列表中)。因此,在查找其他库或编写自己的代码之前,请记住查看这两个实用程序类的可重用方法。

11.优先使用concurrent collections ,少用 synchronized 块

当你必须在多线程应用程序中使用集合时,请考虑在java.util.concurrent 包中使用并发集合,  而不是使用Collections.synchronizedXXX() 方法生成的同步集合  
这是因为并发集合旨在通过实现不同的同步机制(如写时复制,比较和交换以及特殊锁定),在并发应用程序中可以达到最好性能。以下列表显示了如何选择一些并发集合(右侧),它们与正常集合(左侧)相同:

- HashMap -> ConcurrentHashMap

- ArrayList -> CopyOnWriteArrayList

- TreeMap -> ConcurrentSkipListMap

- PriorityQueue -> PriorityBlockingQueue

本文翻译自谷歌Java社群,由于本人水平有限,可能翻译的不够准确,如有错误欢迎指正!

原文链接:http://java-developers-guide.blogspot.com/2018/06/guide-to-best-practices-to-java.html?spref=gp



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值