泛型、Lamdba表达式和Stream流

泛型

1.什么是泛型?

Java 的泛型可以让程序员编写一个类或方法,可以在不指定具体类型的情况下,使用一个类型参数来代替具体的类型,这个参数代表了一个未知的类型,它需要在使用时被指定为一个具体的类型。

2.泛型的优点是?

编译时提高效率,减少类型转化的时间;防止类型转换出现问题,推荐使用各种泛型接口,类
常用的类型占位符:T E K V等。

3.什么是泛型类,泛型接口,泛型方法?
  • 泛型类或接口: Java 中可以定义泛型类和泛型接口,泛型类和泛型接口中可以包含泛型方法,这些方法的类型参数可以是泛型类或泛型接口中定义的类型参数,也可以是自己定义的类型参数。我们定义了一个泛型类 Pair,它有两个类型参数 T 和 E,表示成对的两个值的类型。它有一个构造方法,接受两个参数,一个是类型为 T 的第一个值,一个是类型为 E 的第二个值。
public class Pair<T, E> {
    private T first;
    private E second;
    
    public Pair(T first, E second) {
        this.first = first;
        this.second = second;
    }
    
    public T getFirst() {
        return first;
    }
    
    public E getSecond() {
        return second;
    }
    
    public void setFirst(T first) {
        this.first = first;
    }
    
    public void setSecond(E second) {
        this.second = second;
    }
}
  • 泛型方法:泛型方法可以定义在普通类中,也可以定义在泛型类中。以下是一个泛型方法 printArray 的定义:
public static <T> void printArray(T[] arr) {
    for (T t : arr) {
        System.out.println(t);
    }
}
  • 用泛型写一个通用查询方法:
//   利用泛型写通用查询
    public static <T> List<T> query(Class<T> tClass,String sql,Object... params){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<T> list = new ArrayList<>();

        try {
            connection = getConn();
            statement = connection.prepareStatement(sql);
            setParams(statement,params);
            resultSet = statement.executeQuery();
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            while(resultSet.next()){
                T tObj = tClass.newInstance();//获取T的对象
                //获取结果集中各个字段
                for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
                    String columnName = resultSetMetaData.getColumnLabel(i);
                    Object columnValue= resultSet.getObject(i);
                    //获取字段名对应的实体类型的属性(Field)
                    Field field = tClass.getDeclaredField(columnName);
                    field.setAccessible(true);
                    if(columnValue instanceof Long) {
                        Long value = (Long) columnValue;
                        if (field.getType() == int.class) {//如果实体中该字段为int类型
                            field.set(tObj, value.intValue());//设置属性值,
                        }
                    }else  if(columnValue instanceof Date){
                        Date value = (Date) columnValue;
                        if(field.getType() == LocalDate.class){//如果实体中该字段为int类型
                            field.set(tObj,value.toLocalDate());//设置属性值,
                        }
                    }else{
                        field.set(tObj, columnValue);//设置属性值
                    }
                }
                list.add(tObj);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return list;
    }
4. 什么是通配符,在泛型中有什么用?
  • 通配符:泛型支持通配符,用于表示某个类型的子类或父类,这个通配符用 ? 表示。使用通配符时,我们可以指定一个上界或下界,也可以不指定边界。
  • 使用通配符时,我们可以在前面加上 ? extends 表示这个通配符代表一个上界,或者在前面加上 ? super 表示这个通配符代表一个下界。用一个例子看看:
public class TeFruitDemo {
    public static void main(String[] args) {
        Fruit fruit = new Apple();
        Fruit fruit1 = new Banana();
        List<Fruit> list1 = new ArrayList<>();
        List<Apple> list2 = new ArrayList<>();
        List<Banana> list3 = new ArrayList<>();

        method1(list1);
        method2(list1);
        method2(list2);
        method2(list3);
        method3(list2);
        method3(list1);
//        method3(list3); 错误的

    }
//    如何限定泛型的 边界(范围 )
    static void method1(List<Fruit> list){

    }

//    可以传递List<Fruit>可以List<Apple>
//    限定泛型上边界:1、Fruit 2、继承自Fruit的子类
    static void method2(List<? extends Fruit> list){
    }

//    可以传递List<Apple> 或者List<Apple的父类型> 或者 List<Object>
//    限定泛型下边界:1、Apple 2、Apple的父类型
    static  void method3(List<? super Apple> list){
    }
}

Lamdba表达式

1.什么时候使用Lamdba表达式,它有什么作用?

Lamdba表达式:主要用于简化使用函数接口的代码。所谓函数接口就是只有一个抽象方法的接口,而 Lambda 表达式可以实现这种函数接口的实例化与调用。这种特性可以大量简化代码,提高开发效率。

2.Lamdba表达式的语法以及结构有哪些?
  • 基本语法如下:parameters 表示参数列表,expression 表示方法体。如果参数列表为空,则可以省略小括号;如果方法体中只有一条语句,则可以省略大括号。

(parameters) -> expression

  • 具体示例:
    一个参数:
x -> System.out.println(x)

(x) -> System.out.println(x)

(String x) -> System.out.println(x)

多个参数:

(x, y) -> System.out.println(x + " " + y)

没有参数时:

() -> System.out.println("Hello world!")

当方法体有多行代码时:

x -> {
    int a = x + 1;
    int b = x + 2;
    return a + b;
}
3.结合具体场景该如何使用?
  • 使用规则:Lambda 表达式通常用于接口实现,或函数式接口(functional interface)的调用。函数式接口指只有一个抽象方法的接口。
  • 了解四种类型的函数式接口:①功能型接口:Funcation —有参数有返回值;②消费型接口:Consumer—有参数无返回值③供给型接口:Supplier—无参数有返回值④断言型接口:Predicate—有参数返回Boolean类型。
  • 具体使用场景:以供给型为例子,实现字符串的截取。
//方法引用,函数式接口
public class SubStringFsDemo {
    public static void main(String[] args) {
//        无参有返回值
        Supplier<String> s1 = () -> "hello".toUpperCase();
        System.out.println(s1.get());
        Supplier<String> s2 = "hello"::toUpperCase;
        System.out.println(s2.get());

//        字符串截取
        String str = "hello";
        String result = str.substring(1);
        System.out.println(result);

        //        实例方法引用将中
        Function<Integer,String> f1 = (start) ->"hello".substring(start);
        System.out.println(f1.apply(2));
        Function<Integer,String> f2 = "hello"::substring;
        System.out.println(f2.apply(2));

//
        //Lambda表达式被类的实例方法引用替代的时候
        //表达式中的第一个参数作为调用者
        //后面的参数全部传递给要引用的方法作为参数
//        str1是方法的调用者,start作为lambda体中方法的参数使用

        MySubStr sub1 = (str1,start) ->str1.substring(start);
        System.out.println(sub1.subStr("abcde", 1));
//        方法的引用
        MySubStr sub2 = String::substring;
        System.out.println(sub2.subStr("abcde", 1));


    }
}

interface MySubStr{
//    参数1:要截取的原始字符串
//   参数2: 截取的开始索引
    String subStr(String str,int start);
}
4.方法引入,为何要进行方法引入?
  • 方法引入是啥:通过方法名称引用方法的形式可读性更高一些,这种形式就是方法引用。方法引用是一种更简洁易懂的lambda 表达式替换,实现Lamdba表达式的简写。
  • 语法规则:方法引用中::后只是方法名。看下边的例子:

list.forEach((s) -> System.out.println(s));
list.forEach(Syetem.out::println);

  • 当然的还有对静态方法,实例方法和构造方法的引用。

Stream流

1.什么是Stream流?

Stream(流)是一个来自数据源的元素队列并支持聚合操作。Stream操作还有两个基础的特征:Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格, 可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting);内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

2.如何生成流,如何操作Stream流?
  • 生成流:集合接口有两种方式生成流:stream() − 为集合创建串行流,parallelStream() − 为集合创建并行流。
  • 操做流的方法:
  • 'forEach’来迭代流中的每个数据,使用 forEach 输出了10个随机数:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
  • map 方法用于映射每个元素到对应的结果,使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
  • filter 方法用于通过设置的条件过滤出元素,使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
  • limit 方法用于获取指定数量的流,使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
  • 并行也有许多方法,接下来以一个实例进行展示:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;
 
public class Java8Tester {
   public static void main(String args[]){
      System.out.println("使用 Java : ");
        
      // 计算空字符串
      List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
      System.out.println("列表: " +strings);
      long count = getCountEmptyStringUsingJava7(strings);
        
      System.out.println("空字符数量为: " + count);
      count = getCountLength3UsingJava7(strings);
        
      System.out.println("字符串长度为 3 的数量为: " + count);
        
      // 删除空字符串
      List<String> filtered = deleteEmptyStringsUsingJava7(strings);
      System.out.println("筛选后的列表: " + filtered);
        
      // 删除空字符串,并使用逗号把它们合并起来
      String mergedString = getMergedStringUsingJava7(strings,", ");
      System.out.println("合并字符串: " + mergedString);
      List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        
      // 获取列表元素平方数
      List<Integer> squaresList = getSquares(numbers);
      System.out.println("平方数列表: " + squaresList);
      List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
        
      System.out.println("列表: " +integers);
      System.out.println("列表中最大的数 : " + getMax(integers));
      System.out.println("列表中最小的数 : " + getMin(integers));
      System.out.println("所有数之和 : " + getSum(integers));
      System.out.println("平均数 : " + getAverage(integers));
      System.out.println("随机数: ");
        
      // 输出10个随机数
      Random random = new Random();
        
      for(int i=0; i < 10; i++){
         System.out.println(random.nextInt());
      }
        
      System.out.println("使用 Java 8: ");
      System.out.println("列表: " +strings);
        
      count = strings.stream().filter(string->string.isEmpty()).count();
      System.out.println("空字符串数量为: " + count);
        
      count = strings.stream().filter(string -> string.length() == 3).count();
      System.out.println("字符串长度为 3 的数量为: " + count);
        
      filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList());
      System.out.println("筛选后的列表: " + filtered);
        
      mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", "));
      System.out.println("合并字符串: " + mergedString);
        
      squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
      System.out.println("Squares List: " + squaresList);
      System.out.println("列表: " +integers);
        
      IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();
        
      System.out.println("列表中最大的数 : " + stats.getMax());
      System.out.println("列表中最小的数 : " + stats.getMin());
      System.out.println("所有数之和 : " + stats.getSum());
      System.out.println("平均数 : " + stats.getAverage());
      System.out.println("随机数: ");
        
      random.ints().limit(10).sorted().forEach(System.out::println);
        
      // 并行处理
      count = strings.parallelStream().filter(string -> string.isEmpty()).count();
      System.out.println("空字符串的数量为: " + count);
   }
    
   private static int getCountEmptyStringUsingJava7(List<String> strings){
      int count = 0;
        
      for(String string: strings){
        
         if(string.isEmpty()){
            count++;
         }
      }
      return count;
   }
    
   private static int getCountLength3UsingJava7(List<String> strings){
      int count = 0;
        
      for(String string: strings){
        
         if(string.length() == 3){
            count++;
         }
      }
      return count;
   }
    
   private static List<String> deleteEmptyStringsUsingJava7(List<String> strings){
      List<String> filteredList = new ArrayList<String>();
        
      for(String string: strings){
        
         if(!string.isEmpty()){
             filteredList.add(string);
         }
      }
      return filteredList;
   }
    
   private static String getMergedStringUsingJava7(List<String> strings, String separator){
      StringBuilder stringBuilder = new StringBuilder();
        
      for(String string: strings){
        
         if(!string.isEmpty()){
            stringBuilder.append(string);
            stringBuilder.append(separator);
         }
      }
      String mergedString = stringBuilder.toString();
      return mergedString.substring(0, mergedString.length()-2);
   }
    
   private static List<Integer> getSquares(List<Integer> numbers){
      List<Integer> squaresList = new ArrayList<Integer>();
        
      for(Integer number: numbers){
         Integer square = new Integer(number.intValue() * number.intValue());
            
         if(!squaresList.contains(square)){
            squaresList.add(square);
         }
      }
      return squaresList;
   }
    
   private static int getMax(List<Integer> numbers){
      int max = numbers.get(0);
        
      for(int i=1;i < numbers.size();i++){
        
         Integer number = numbers.get(i);
            
         if(number.intValue() > max){
            max = number.intValue();
         }
      }
      return max;
   }
    
   private static int getMin(List<Integer> numbers){
      int min = numbers.get(0);
        
      for(int i=1;i < numbers.size();i++){
         Integer number = numbers.get(i);
        
         if(number.intValue() < min){
            min = number.intValue();
         }
      }
      return min;
   }
    
   private static int getSum(List numbers){
      int sum = (int)(numbers.get(0));
        
      for(int i=1;i < numbers.size();i++){
         sum += (int)numbers.get(i);
      }
      return sum;
   }
    
   private static int getAverage(List<Integer> numbers){
      return getSum(numbers) / numbers.size();
   }
}

本篇到此结束,感谢学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值