欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java8中lambda表达式的应用及一些泛型相关知识

程序员文章站 2024-03-08 16:55:10
语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记...

语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利

顺带用到一些泛型编程,一切都是为了简化代码

场景:

一个数据类,用于记录职工信息

public class employee {
 public string name;
 public int age;
 public char sex;
 public string time;
 public int salary;
}

我们有一列此类数据

list<employee> data = arrays.aslist(e1,e2,e3......)

现在有需求:将员工employee按照姓名的首字母(假设均为英文名)进行分组:

那么我们要得到的结果应该是一个map:char -> list<employee> 这样的映射关系

public static map<character, list<employee>> groupbyfirstchar(
 list<employee> data){
  map<character, list<employee>> result = new hashmap<>();
  for(employee e : data){
   character c = e.name.charat(0);
   list<employee> l = result.get(c);
   if(l == null){
    l = new arraylist<>();
    result.put(c, l);
   }
   l.add(e);
  }
  return result;
}

代码并不复杂,很快就可以完成,老板看你效率这么高,于是说,再按照工资分个组吧,5000以下的,5000~10000的 ...等

也不会太难,将key换一下,稍作逻辑处理即可

public static map<string, list<employee>> groupbysalary(list<employee> data) {
 map<string, list<employee>> result = new hashmap<>();
 for (employee e : data) {
  string key = separate(e.salary);
  list<employee> l = result.get(key);
  if (l == null) {
   l = new arraylist<>();
   result.put(key, l);
  }
  l.add(e);
 }
 return result;<br>}
private static string separate(int salary) {
 if (salary <= 5000) {
  return "5000以下";
 }
 if (salary <= 10000) {
   return "5000~10000";
 }
 if (salary <= 20000) {
  return "10000~20000";
 }
 return "20000以上"
}

然后老板又说了,按照员工的入职年份分下组吧。。。

这里就代码就不写了,稍作比较可以发现,无论怎么分组,唯一的变化是key值的选取方式,

第一次将employee的name的第一字母作为key:

employee e -> e.name.charat(0)

第二次将employee的salary按照方法separat转换为string作为key:

employee e -> separate(e.salary):string

以此类推

employee e -> getyear(e.time):string

事实上第一次也可以将获取首字母单独写成一个方法

employee e -> getfirstchar(e.name):character

为了看起来更美观,可以讲三个方法的参数都设置成employee 方法体就不写了 这里只列出参数和返回值

employee e -> getfirstchar(e) : character
employee e -> separate(e) : string
employee e -> getyear(e) : string

->的左边为参数,:的右边为返回值,->的右边是方法的签名

那么我们自然会想到将变化的部分抽取为参数,其他不变的部分抽取为方法体,那么就可以省去那些重复的代码,显然变化的部分就是上面列出的,将employee e转化成key的方法,但是我们知道java是不能把方法作为参数进行传递的。不过对于稍有经验的程序猿来说这并不是问题,我们可以使用接口来实现我们的目的,同时又会遇到另一个问题,以上三个方法的返回值是不同的,因此我们要用到泛型:

public static <k> map<k, list<employee>> groupbykey(list<employee> data, getkey<k> getkey){
 map<k, list<employee>> result = new hashmap<>();
 for(employee e : data) {
  k key = getkey.getkey(e);
  list<employee> l = result.get(key);
  if (l == null) {
   l = new arraylist<>();
   result.put(key, l);
  }
  l.add(e);
 }
  return result;
}
interface getkey<k>{
 k getkey(employee e);
}

那么上面的第一个需求就可以这样实现

map<character, list<employee>> result = groupbykey(data, new getkey<character>() {
   @override
   public character getkey(employee e) {
    e.name.charat(0);
   }
  });

第二个需求

map<string, list<employee>> result = groupbykey(list, new getkey<string>() {
   @override
   public string getkey(employee e) {
    separate(e.salary);
   }
  });

可以发现,我们只需要更改泛型参数和匿名内部类的实现即可,唯一的问题恐怕是这么写实在不太好看,而且很多例行公事的代码,尤其体现在匿名内部类上。

事实上我们只关心这个匿名内部类的参数和返回值,其他部分仅仅是语法要求。

java8恰好为我们提供了很好的方式来避免复杂的例行公事的方式:lambda表达式,以上实现就可以写成

map<character, list<employee>> resultbyfirstchar = groupbykey(list, e -> e.name.charat(0));
map<string, list<employee>> resultbysalary = groupbykey(list, e -> separate(e.salary));

lambda表达式恰恰只表现出我们所关心的,参数和返回值,同时由于类型推断,可以省去参数类型,具体语法这里就不介绍了,网上可以查到很多资料

extra:

如果你对泛型有不错的了解的话,方法groupbykey还可以进一步抽象:

public static <k, e> map<k, list<e>> groupby(list<? extends e> data, function<? super e, ? extends k> fun) {
 map<k, list<e>> result = new hashmap<>();
 for(e e : data) {
  k k = fun.apply(e);<br>  list<e> l = result.get(k);
  if(l == null) {
   l = new arraylist<>();
   result.put(k, l);
  }
  l.add(e);
 }
 return result;<br>
 }

我们将employee这个类也抽取了,好处显而易见

function接口是java8新加入的接口:

@functionalinterface
public interface function<t, r> {
 r apply(t t);
}

输入一个t类型 返回r类型。泛型和函数式编程结合的很不错,虽然java8的新特性被各种吐槽,但是能带来好处总是好的,这给了我们更多的选择。

有时间的话会介绍stream,java8的另一大利器

以上所述是小编给大家介绍的java8中lambda表达式的应用及一些泛型相关知识,希望对大家有所帮助