前言
数据去重是项目中经常出现的应用场景,并且面试中可能也会问到,那么你会几种数组去重方式呢?
实战
使用额外空间去重
List<String> list = Arrays.asList("java", "html", "js", "sql", "java");
@Test
public void test8() {
List<String> newList = new ArrayList<>();
for (String el : list) {
if(!newList.contains(el)) {
newList.add(el);
}
}
System.out.println(newList);
}
复制代码
优点:实现简单、并且在循环判断过程中可以增加额外操作
缺点:需要一个额外空间大小的数组,浪费空间,多行代码实现
Set集合自动去重
List<String> list = Arrays.asList("java", "html", "js", "sql", "java");
@Test
public void test8() {
Set<String> set = new HashSet<>(list);
List<String> newList = new ArrayList<>(set);
System.out.println(newList);
}
复制代码
优点:利用
Set
集合的不重复特性去重更简单缺点:使用额外空间,需要来回转换,不太优雅
Java8一键去重(distinct)
List<String> list2 = Arrays.asList("java", "html", "js", "sql", "java");
@Test
public void test9() {
// java8 stream-api去重
list2.stream()
.distinct()
.forEach(System.out::println);
}
复制代码
优点:java8新特性,流式操作简单方便(和sql一样),代码优雅
缺点:无法在去重的过程中进行额外操作
distinct去重注意事项
既然这么好用,那distinct是通过什么去重的呢?如果是引用类型,是通过地址去重还是通过某些字段去重呢?
-
distinct去重失效示例代码
List<Employee> list = Arrays.asList( new Employee( "小明", 18), new Employee( "赵六", 38), new Employee( "张三", 6), new Employee( "小明", 18) ); class Employee { private String name; private Integer age; public Employee(String name, Integer age) { this.name = name; this.age = age; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + '}'; } } @Test public void test9() { list.stream() .distinct() .forEach(System.out::println); } 复制代码
控制台输出:
Employee{name='小明', age=18} Employee{name='赵六', age=38} Employee{name='张三', age=6} Employee{name='小明', age=18} 复制代码
结果:使用自定义对象
distinct
无法去重,难道distinct
无法作用引用类型吗?但是刚才的String
也是引用类型,但是也可以去重。自定义的对象Employee
和String
有什么区别吗?没错,就是hashcode()
和equals()
方法,String
已经重写了这两个方法,自定义的Employee
没有重写这两个方法。注意:只要是涉及
Map
和Set
这种去重的集合,或者Java8的distinct
去重,都是通过hashcode()
和equals
来作为数据去重的依据,所以要注意重写这两个方法 -
修改测试
class Employee { private String name; private Integer age; ... // 重写equals和hashcode方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; return Objects.equals(name, employee.name) && Objects.equals(age, employee.age); } @Override public int hashCode() { return Objects.hash(name, age); } ... } @Test public void test9() { list.stream() .distinct() .forEach(System.out::println); } 复制代码
控制台输出:
Employee{name='小明', age=18} Employee{name='赵六', age=38} Employee{name='张三', age=6} 复制代码
重写
hashcode
和equals
可以实现去重。
小总结
无论使用Set
集合去重还是使用Java8的新特性stream流的distinct
去重,都是通过hashcode()
和equals()
自定义的策略进行去重。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END