英文链接源链接 [13953]
  • 《Java8》教程

contenteditable="true"

Java 8 Interview Questions 介绍

亲爱的读者,这些 Java 8面试问题是专门设计的,目的是让您熟悉在采访中可能会遇到的关于 Java 8语言主题的问题的性质。根据我的经验,优秀的面试官几乎不会计划在面试过程中提出任何特定的问题,通常,问题是从该主题的一些基本概念开始的,后来根据进一步的讨论和您的回答,这些问题会继续出现-

Java 8中添加了许多功能,最重要的功能在下面提到-

  • Lambda表达式-向Java添加功能处理功能。

  • 方法引用-通过函数名称进行引用,而不是直接调用它们。使用函数作为参数。

  • 默认方法-具有默认方法实现的接口。

  • 新工具-添加了新的编译器工具和实用程序,例如" jdeps",以找出依赖性。

  • Stream API -简化流水线处理的新流API。

  • 日期时间API -改进的日期时间API。

  • 可选-强调正确处理空值的最佳做法。

  • Nashorn,JavaScript引擎-用于执行JavaScript代码的基于Java的引擎。

与这些新功能一起,在编译器和JVM级别进行了许多功能增强。

以下代码使用Java 8 lambda表达式对字符串列表进行排序:

//sort using java 8
private void sortUsingJava8(List<String> names) {
  Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}

Lambda表达式的特征在于以下语法-

parameter −> expression body

以下是lambda表达式的重要特征-

  • 可选类型声明-无需声明参数的类型。编译器可以从参数的值推断出相同的含义。

  • 参数周围的可选括号-无需在括号中声明单个参数。对于多个参数,需要括号。

  • 可选的花括号-如果主体包含单个语句,则无需在表达式主体中使用花括号。

  • 可选的return关键字-如果主体具有单个表达式以返回值,则编译器自动返回该值。需要大括号表示表达式返回一个值。

Lambda表达式主要用于定义功能接口的内联实现,即仅具有单个方法的接口。在上面的示例中,我们使用了各种类型的lambda表达式来定义MathOperation接口的操作方法。然后,我们定义了GreetingService的sayMessage的实现。

Lambda表达式消除了对匿名类的需求,并为Java提供了非常简单而强大的功能编程能力。

使用lambda表达式,您可以引用最终变量或有效地引用最终变量(仅分配一次)。如果第二次为变量赋值,则Lambda表达式将引发编译错误。

方法引用有助于通过名称来指向方法。使用::(双冒号)符号描述方法引用。方法参考可用于指出以下类型的方法-

  • 静态方法

  • 实例方法

  • 使用新运算符(TreeSet :: new)的构造函数

System.out :: println方法是对System类的out对象的println方法的静态方法引用。

功能接口具有单个功能。例如,具有单个方法" compareTo"的Comparable接口用于比较目的。 Java 8定义了许多在lambda表达式中广泛使用的功能接口。

它表示一个接受两个输入参数且不返回结果的操作。

它代表一个接受两个参数并产生结果的函数。

它表示对两个相同类型的操作数的运算,产生与该操作数相同类型的结果。

它表示两个参数的谓词(布尔值函数)。

它表示布尔值结果的提供者。

它表示一个接受单个输入参数且不返回结果的操作。

它表示对两个双值操作数的运算并产生双值结果。

它表示一个接受单个双值参数且不返回结果的操作。

它代表一个接受双值参数并产生结果的函数。

它表示一个双值参数的谓词(布尔值函数)。

它代表了具有双重价值的结果。

它表示一个函数,该函数接受双值参数并产生一个int值的结果。

它表示一个接受双值参数并产生长值结果的函数。

它表示对单个双值操作数的操作,该操作产生双值结果。

它代表一个接受一个参数并产生结果的函数。

它表示对两个int值操作数的运算,并产生int值的结果。

它表示一个接受单个int值参数且不返回结果的操作。

它表示一个接受一个int值参数并产生结果的函数。

它表示一个int值参数的谓词(布尔值函数)。

它代表具有int值的结果的供应商。

它表示一个函数,该函数接受一个int值的参数并产生一个双值的结果。

它表示一个接受整数值参数并产生长值结果的函数。

它表示对单个int值操作数的操作,该操作数产生int值的结果。

它表示对两个长值操作数的运算,并产生长值结果。

它表示一个接受单个长值参数且不返回结果的操作。

它代表一个接受长值参数并产生结果的函数。

它表示一个长值参数的谓词(布尔值函数)。

它代表着具有长期价值的结果。

它表示一个函数,该函数接受长值参数并产生双值结果。

它表示一个函数,该函数接受一个长值参数并产生一个int值的结果。

它表示对单个长值操作数的操作,该操作数产生长值结果。

它表示一个接受对象值和双值参数的操作,不返回任何结果。

它表示一个操作,该操作接受对象值和int值的参数,并且不返回任何结果。

它表示一个接受对象值和长值参数的操作,不返回任何结果。

它表示一个参数的谓词(布尔值函数)。

它代表结果的提供者。

它代表一个接受两个参数并产生双值结果的函数。

它表示产生双值结果的函数。

它表示一个接受两个参数并产生int值的结果的函数。

它代表一个产生整数值结果的函数。

它表示一个接受两个参数并产生长值结果的函数。

它表示一个产生长值结果的函数。

它表示对单个操作数的操作,该操作产生与其操作数类型相同的结果。

使用Java 8,接口可以在接口中具有函数的默认实现。

从Java 8开始,接口也可以具有静态帮助器方法。

public interface vehicle {
   default void print() {
      System.out.println("I am a vehicle!");
   }
 
   static void blowHorn() {
      System.out.println("Blowing horn!!!");
   }
}

与接口名称一起使用super关键字。

interface Vehicle {
   default void print() {
      System.out.println("I am a vehicle!");
   }
}
class Car implements Vehicle {
   public void print() {
      Vehicle.super.print();                  
   }
}

使用接口的名称。

interface Vehicle {
   static void blowHorn() {
      System.out.println("Blowing horn!!!");
   }
}
class Car implements Vehicle {
   public void print() {
      Vehicle.blowHorn();                  
   }
}

流表示来自源的一系列对象,支持聚合操作。

大多数流操作返回流本身,以便可以对它们的结果进行流水线处理。这些操作称为中间操作,其功能是获取输入,处理它们并将输出返回给目标。 collect()方法是一种终端操作,通常出现在流水线操作的结尾以标记流的结尾。

与需要显式迭代的Collections相反,流操作在内部对提供的源元素进行迭代。

Stream提供了一种新的" 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);
//get list of unique squares
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

"过滤器"方法用于根据标准消除元素。

下面的代码段使用过滤器打印空字符串的计数。

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.stream().filter(string −> string.isEmpty()).count();

"限制"方法用于减小流的大小。

以下代码段显示了如何打印10个随机数。

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

"排序"方法用于对流进行排序。

以下代码段显示了如何按排序顺序打印10个随机数。

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

parallelStream是并行处理流的替代方法。看一下下面的代码段,该代码段使用parallelStream打印一串空字符串。

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.parallelStream().filter(string −> string.isEmpty()).count();
//It is very easy to switch between sequential and parallel streams.

收集器用于合并对流元素的处理结果。收集器可用于返回列表或字符串。

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);

在Java 8中,引入了统计信息收集器以在完成流处理时计算所有统计信息。

以下代码将打印列表中出现的最高编号。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());

以下代码将打印列表中出现的最高编号。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Lowest number in List : " + stats.getMin());

以下代码将打印列表中所有数字的总和。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Sum of all numbers : " + stats.getSum());

以下代码将打印列表中所有数字的平均值。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) −> x).summaryStatistics();
System.out.println("Average of all numbers : " + stats.getAverage());

可选的是一个容器对象,用于包含非空对象。可选对象用于表示缺少值的null。此类具有各种实用程序方法,以方便代码将值处理为"可用"或"不可用",而不是检查空值。它是Java 8中引入的,类似于Guava中的Optional。

在Java 8 Nashorn中,引入了经过改进的javascript引擎,以取代现有的Rhino。 Nashorn提供了2至10倍的性能提升,因为它可以直接编译内存中的代码并将字节码传递给JVM。 Nashorn使用Java 7中引入的invokedynamics功能来提高性能。

对于Nashorn引擎,JAVA 8引入了新的命令行工具jjs,以在控制台上执行javascript代码。

是!使用ScriptEngineManager,可以用Java调用和解释JavaScript代码。

本地-简化的日期时间API,没有时区处理的复杂性。

分区-专门的日期时间API,用于处理各种时区。

在Java 8中添加了java.time.temporal.ChronoUnit枚举,以替换旧API中用于表示日,月等的整数值。

以下代码使用本地datetime api获取当前日期-

//Get the current date
LocalDate today = LocalDate.now();
System.out.println("Current date: " + today);

以下代码使用本地datetime api将1周添加到当前日期-

//add 1 week to the current date
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("Next week: " + nextWeek);

以下代码使用本地datetime API将1个月添加到当前日期:

//add 1 month to the current date
LocalDate today = LocalDate.now();
LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
System.out.println("Next month: " + nextMonth);

以下代码使用本地datetime API将1年添加到当前日期-

//add 1 year to the current date
LocalDate today = LocalDate.now();
LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("Next year: " + nextYear);

以下代码使用本地datetime API将10年添加到当前日期-

//add 10 years to the current date
LocalDate today = LocalDate.now();
LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
System.out.println("Date after ten year: " + nextDecade);

以下代码使用Java8在下周二获得-

//get the next tuesday
LocalDate today = LocalDate.now();
LocalDate nextTuesday = today.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println("Next Tuesday on : " + nextTuesday);

以下代码使用java8获取下个月的第二个星期六-

//get the second saturday of next month
LocalDate firstInYear = LocalDate.of(date1.getYear(),date1.getMonth(), 1);
LocalDate secondSaturday = firstInYear.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
System.out.println("Second Saturday on : " + secondSaturday);

以下代码以毫秒为单位获取当前日期的时刻-

//Get the instant of current date in terms of milliseconds
Instant now = currentDate.toInstant();

以下代码使用毫秒为单位的时间获取本地日期时间的瞬间-

Instant now = currentDate.toInstant();
ZoneId currentZone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(now, currentZone);
System.out.println("Local date: " + localDateTime);

以下代码使用毫秒为单位的时间获取分区日期时间的瞬间-

Instant now = currentDate.toInstant();
ZoneId currentZone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, currentZone);
System.out.println("Zoned date: " + zonedDateTime);

静态类Base64.Decoder-此类实现了一个解码器,用于使用RFC 4648和RFC 2045中指定的Base64编码方案来解码字节数据。

静态类Base64.Encoder-此类实现了一个编码器,用于使用RFC 4648和RFC 2045中指定的Base64编码方案对字节数据进行编码。

Base64类的getDecoder()方法返回一个Base64.Decoder,它使用基本类型base64编码方案进行解码。

Base64类的getEncoder()方法返回一个Base64.Encoder,它使用基本类型base64编码方案进行编码。

Base64类的getMimeDecoder()方法返回一个Base64.Decoder,它使用MIME类型base64解码方案进行解码。

Base64类的getMimeEncoder()方法返回一个Base64.Encoder,它使用MIME类型base64编码方案进行编码。

Base64类的getUrlDecoder()方法返回一个Base64.Decoder,该解码器使用URL和Filename安全类型base64编码方案进行解码。

Base64类的getUrlEncoder()方法返回一个Base64.Encoder,它使用URL和Filename安全类型base64编码方案进行编码。

下一步是什么?

此外,您可以浏览过去完成的与该主题相关的作业,并确保您能够自信地对它们发表讲话。如果您是新手,那么面试官不会期望您会回答非常复杂的问题,而是必须使您的基本概念非常扎实。

第二,如果您不能回答几个问题,那实际上并不重要,但是无论您回答了什么,您都必须自信地回答,这很重要。因此,在面试中要感到自信。我们在tutorialspoint上祝您好运,有一位优秀的面试官,并祝您未来事业一切顺利。欢呼声:-)

点我分享笔记