㈠ java中for each的用法
foreach语句是java5的新特征之一,在遍历数组、集合方面,foreach为开发人员提供了极大的方便。
foreach语句是for语句的特殊简化版本,但是foreach语句并不能完全取代for语句,然而,任何的foreach语句都可以改写为for语句版本。
foreach并不是一个关键字,习惯上将这种特殊的for语句格式称之为“foreach”语句。从英文字面意思理解foreach也就是“for 每一个”的意思。实际上也就是这个意思。
foreach的语句格式:
for(元素类型t 元素变量x : 遍历对象obj){
引用了x的java语句;
}
下面通过两个例子简单例子看看foreach是如何简化编程的。代码如下:
一、foreach简化数组和集合的遍历
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
/**
* Created by IntelliJ IDEA.
* User: leimin
* Date: 2007-12-3
* Time: 16:58:24
* Java5新特征之foreach语句使用总结
*/
public class TestArray {
public static void main(String args[]) {
TestArray test = new TestArray();
test.test1();
test.listToArray();
test.testArray3();
}
/**
* foreach语句输出一维数组
*/
public void test1() {
//定义并初始化一个数组
int arr[] = {2, 3, 1};
System.out.println("----1----排序前的一维数组");
for (int x : arr) {
System.out.println(x); //逐个输出数组元素的值
}
//对数组排序
Arrays.sort(arr);
//利用java新特性for each循环输出数组
System.out.println("----1----排序后的一维数组");
for (int x : arr) {
System.out.println(x); //逐个输出数组元素的值
}
}
/**
* 集合转换为一维数组
*/
public void listToArray() {
//创建List并添加元素
List<String> list = new ArrayList<String>();
list.add("1");
list.add("3");
list.add("4");
//利用froeach语句输出集合元素
System.out.println("----2----froeach语句输出集合元素");
for (String x : list) {
System.out.println(x);
}
//将ArrayList转换为数组
Object s[] = list.toArray();
//利用froeach语句输出集合元素
System.out.println("----2----froeach语句输出集合转换而来的数组元素");
for (Object x : s) {
System.out.println(x.toString()); //逐个输出数组元素的值
}
}
/**
* foreach输出二维数组测试
*/
public void testArray2() {
int arr2[][] = {{4, 3}, {1, 2}};
System.out.println("----3----foreach输出二维数组测试");
for (int x[] : arr2) {
for (int e : x) {
System.out.println(e); //逐个输出数组元素的值
}
}
}
/**
* foreach输出三维数组
*/
public void testArray3() {
int arr[][][] = {
{{1, 2}, {3, 4}},
{{5, 6}, {7, 8}}
};
System.out.println("----4----foreach输出三维数组测试");
for (int[][] a2 : arr) {
for (int[] a1 : a2) {
for (int x : a1) {
System.out.println(x);
}
}
}
}
}
运行结果:
----1----排序前的一维数组
2
3
1
----1----排序后的一维数组
1
2
3
----2----froeach语句输出集合元素
1
3
4
----2----froeach语句输出集合转换而来的数组元素
1
3
4
----4----foreach输出三维数组测试
1
2
3
4
5
6
7
8
Process finished with exit code 0
二、foreach语句的局限性
通过上面的例子可以发现,如果要引用数组或者集合的索引,则foreach语句无法做到,foreach仅仅老老实实地遍历数组或者集合一遍。下面看一个例子就明白了:
/**
* Created by IntelliJ IDEA.
* User: leimin
* Date: 2007-12-3
* Time: 17:07:30
* foreach语句的局限性
*/
public class TestArray2 {
public static void main(String args[]) {
//定义一个一维数组
int arr[] = new int[4];
System.out.println("----未赋值前输出刚刚定义的数组----");
for (int x : arr) {
System.out.println(x);
}
//通过索引给数组元素赋值
System.out.println("----通过循环变量给数组元素赋值----");
for (int i = 3; i > 0; i--) {
arr[i] = i;
}
//循环输出创建的数组
System.out.println("----赋值后,foreach输出创建好的数组----");
for (int x : arr) {
System.out.println(x);
}
}
}
运行结果:
----未赋值前输出刚刚定义的数组----
0
0
0
0
----通过循环变量给数组元素赋值----
----赋值后,foreach输出创建好的数组----
0
1
2
3
Process finished with exit code 0
三、总结
foreach语句是for语句特殊情况下的增强版本,简化了编程,提高了代码的可读性和安全性(不用怕数组越界)。相对老的for语句来说是个很好的补充。提倡能用foreach的地方就不要再用for了。在用到对集合或者数组索引的情况下,foreach显得力不从心,这个时候是用for语句的时候了。foreach一般结合泛型使用
㈡ 濡备綍楂樻晥镄勯亶铡哅ap锛熶綘甯哥敤镄勪笉涓瀹氭槸链蹇镄
濡傛枃绔犳爣棰樻墍瑷锛岄亶铡哅ap鏄寮鍙戣繃绋嬩腑姣旇缉甯歌佺殑琛屼负锛屽疄鐜扮殑鏂瑰纺涔熸湁澶氱嶆柟寮忥纴链鏂囧甫棰嗗ぇ瀹朵竴璧风湅鐪嬫洿锷犻珮鏁堢殑阆嶅巻 Map 銆
棣栧厛涓璧锋潵鐪嬬湅锛屾湁鍝浜涢亶铡 Map 镄勬柟寮
杩欑嶅簲璇ョ畻鏄姣旇缉甯歌佺殑浣跨敤鏂瑰纺锛屼篃鏄姣旇缉瀹规槗鐞呜В镄
keySet 锛 銮峰彇 map 涓镓链夌殑 key 锛岀劧钖庝緷娆¢亶铡嗘疮涓 key 銆
杩欑嶆槸鎴戝钩镞跺紑鍙戜腑鐢ㄧ殑链澶氱殑鏂瑰纺锛岀亩鍗曢氢织鏄撴哕銆
浣嗘槸鍏舵ц兘濡备綍锻锛熷悗缁寰呮彮绉樸
涓岖煡阆撴湁澶氩皯浜虹敤杩 Java8 涓镄 parallel妯″纺锛屾湰璐ㄦ槸涓绉嶅苟琛屽勭悊鏂瑰纺銆
镐ц兘濡备綍锛熺◢钖庢彮鏅撱
涓嶈屽氨镓炬垒澶栨彺璇曡瘯锛
娴嬭瘯鐜澧冨备笅锛欼ntel i7-4790 3.60 GHz, 16 GB
娴嬭瘯闆嗕负灏忕殑Map闆嗗悎锛埚ぇ绾100涓鍏幂礌锛夛纴钖勪釜鏂规硶钥楁椂濡备笅锛
浠庣粨鏋灭湅鍑猴纴鍦ㄦ暟鎹閲忔瘆杈冨皬镞讹纴 鍒╃敤 Java 8涓镄刦oreach 𨱌傛椂棰嗗厛銆
娴嬭瘯闆嗕负鍏幂礌鏁版嵁閲 1000 镄 Map 闆嗗悎锛屾祴璇旷粨鏋滃备笅锛
浠庣粨鏋滈泦钖堢湅锛屽湪涓绛夋暟鎹閲忔儏鍐典笅锛屽栨彺 Eclipse (CS) collections 涓镄 MutableMap 琛ㄧ幇链涓轰紭寮傦纴鍕囧缑绗涓銆
鍏舵′负 Java 8 涓镄 foreach 锛屼綅鍒楃浜屻
娴嬭瘯闆嗕负鍏幂礌鏁版嵁閲 100000 锛埚崄涓囩骇鍒锛 镄 Map 闆嗗悎锛屾祴璇旷粨鏋滃备笅锛
鍒╃敤 iterator 鍜 Map.Entry 銆愭柟娉1銆戠ǔ灞呯涓锛岄嗗厛 绗浜屽悕宸涓嶅7s銆
绗浜屽悕涓 Eclipse (CS) collections 涓镄 MutableMap 浣嶅垪绗浜岋纴鍦ㄥぇ鏁版嵁閲忎笅琛ㄧ幇琛ㄧ幇姣旇缉鍑鸿壊銆
鎸囩殑娉ㄦ剰镄勬槸涔嫔墠鍦ㄥ皬鏁版嵁閲忎笅琛ㄧ幇姣旇缉鍑鸿壊镄 Java 8 涓镄 foreach 锛屾帓钖嶅嵈姣旇缉闱犲悗锛屼絾鏄浠岖劧瓒呰繃浜嗗埄鐢 Java8 镄 Stream API 銆
鍏朵腑杩樻湁鍙︿竴涓鐜拌薄锛氩埄鐢ㄥ苟琛屾ā寮忚$畻镄 Java8 涓镄 Stream API parallel 锛屽湪澶ф暟鎹閲忔椂琛ㄧ幇濂戒簬 foreach 鍜 stream api 銆
涓嬭〃涓轰笉钖屾暟鎹閲忔儏鍐典笅镄勫悇涓鏂规硶镐ц兘琛ㄧ幇
鍦ㄥ钩镞跺紑鍙戜腑锛屾暟鎹閲忛兘涓岖畻澶澶ф椂锛屽墫闄ゅ栨彺钥岃█锛 Java 8 涓镄 foreach 銆愭柟娉3銆戯纴琛ㄧ幇姣旇缉浼桦纾銆傝屽苟琛岃繍绠楃殑 Stream API parallel 銆愭柟娉8銆戣〃鐜版病链夋兂璞′腑濂斤纴 Stream API 銆愭柟娉7銆戣〃鐜颁腑瑙勪腑鐭┿
涓昏佺绥鍒椾简澶氱嶉亶铡 Map 镄勬柟寮忥纴姣忎釜瀹炵幇鏂瑰纺閮芥湁钖勮嚜镄勭壒镣癸纴链夌殑浜哄枩娆 foreach 镄勯氢织鏄撴哕锛涙湁镄勪汉锽沧 stream 镄勫共鍑鍒╄惤銆
濡傛灉浠庢ц兘𨱒ョ湅锛屽皬鏁版嵁閲忔儏鍐典笅锛氢紭鍏堟帹钻愪娇鐢 Java8 Foreach 銆愭柟娉3銆戙
澶ф暟鎹閲忔儏鍐典笅鎺ㄨ崘 浣跨敤 iterator 鍜 Map.Entry 銆愭柟娉1銆戙
鎴戞槸澶ч粍锛屼竴涓鍙浼氩啓 HelloWorld 镄勭▼搴忓憳锛屼笅链熻併
㈢ Java8,stream().map().collect(Collectors.toList()).forEach()和stream().map().forEach()有啥区别
在stream().map().collect(Collectors.toList()).forEach()中,你的forEach()针对的List;而
stream().map().forEach()针对的是Stream流。从结果操作来看是一样的,中间过程回产生一些临时变量。
㈣ Java中怎么遍历map中value值
Java中遍历Map对象的4种方法:
1、通过Map.entrySet遍历key和value,在for-each循环中使用entries来遍历.推荐,尤其是容量大时。
(4)java8foreach扩展阅读:
关于JAVA的遍历知识补充:
1、list和set集合都实现了Iterable接口,所以他们的实现类可以使用迭代器遍历,map集合未实现该接口,若要使用迭代器循环遍历,需要借助set集合。
2、使用EntrySet 遍历,效率更高。
㈤ java涓镄刦oreach寰鐜鍑洪敊锛孲yntax error
链浣崇瓟妗堥敊浜嗭纴澶у跺埆琚璇瀵
1銆
绠鍗曟潵璇达纴JDK1.8涔嫔墠镄刦oreach寰鐜鎸囩殑閮芥槸for寰鐜镄勫彟涓绉岖敤娉:for(Object o : objects)锛屽尯鍒浜庢渶缁忓吀镄刦or(;;)锛岃孞AVA8锛圝DK1.8锛変腑鍦ㄥ筳ava闆嗗悎绫伙纸Set銆丩ist銆丮ap銆丵ueue锛夌殑阆嶅巻涓鏂板炰简涓涓猣oreach镄勭被鏂规硶鐢ㄤ簬闆嗗悎鍐呭惊鐜銆傛墍浠ラ梾棰树腑镄勮娉曟槸鍙鐢ㄧ殑銆
琛ュ厖锛氱敱JDK1.8涓镄勬弿杩帮纴foreach镄勫弬鏁版槸涓涓狢onsumer瀵硅薄锛岃ュ硅薄鏄涓涓鍑芥暟寮忔帴鍙o纴鍑℃槸鍑芥暟寮忔帴鍙g殑瀵硅薄閮藉彲浠ョ洿鎺ヤ娇鐢↙ambda琛ㄨ揪寮忥纴钥岄樼洰涓镄凷ystem.out::println()灏辨槸涓涓绠鍖栦简镄凩ambda锛岀渷鐣ヤ简鍙傛暟鍜屾嫭鍙疯屽凡銆
㈥ Java9都快发布了,Java8的十大新特性你了解多少呢
一、Lambda表达式
Lambda表达式可以说是Java 8最大的卖点,她将函数式编程引入了Java。Lambda允许把函数作为一个方法的参数,或者把代码看成数据。
一个Lambda表达式可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。例如:
Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );
1 Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );
为了使现有函数更好的支持Lambda表达式,Java
8引入了函数式接口的概念。函数式接口就是只有一个方法的普通接口。java.lang.Runnable与java.util.concurrent.Callable是函数式接口最典型的例子。为此,Java
8增加了一种特殊的注解@FunctionalInterface:
1 @FunctionalInterface
2 public interface Functional {
3 void method();
4 }
二、接口的默认方法与静态方法
我们可以在接口中定义默认方法,使用default关键字,并提供默认的实现。所有实现这个接口的类都会接受默认方法的实现,除非子类提供的自己的实现。例如:
1 public interface DefaultFunctionInterface {
2 default String defaultFunction() {
3 return "default function";
4 }
5 }
我们还可以在接口中定义静态方法,使用static关键字,也可以提供实现。例如:
1 public interface StaticFunctionInterface {
2 static String staticFunction() {
3 return "static function";
4 }
5 }
接口的默认方法和静态方法的引入,其实可以认为引入了C++中抽象类的理念,以后我们再也不用在每个实现类中都写重复的代码了。
三、方法引用
通常与Lambda表达式联合使用,可以直接引用已有Java类或对象的方法。一般有四种不同的方法引用:
构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数;
静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数;
特定类的任意对象方法引用。它的语法是Class::method。要求方法是没有参数的;
特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数,与3不同的地方在于,3是在列表元素上分别调用方法,而4是在某个对象上调用方法,将列表元素作为参数传入;
四、重复注解
在Java 5中使用注解有一个限制,即相同的注解在同一位置只能声明一次。Java
8引入重复注解,这样相同的注解在同一地方也可以声明多次。重复注解机制本身需要用@Repeatable注解。Java
8在编译器层做了优化,相同注解会以集合的方式保存,因此底层的原理并没有变化。
五、扩展注解的支持
Java 8扩展了注解的上下文,几乎可以为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。
六、Optional
Java 8引入Optional类来防止空指针异常,Optional类最先是由Google的Guava项目引入的。Optional类实际上是个容器:它可以保存类型T的值,或者保存null。使用Optional类我们就不用显式进行空指针检查了。
七、Stream
Stream
API是把真正的函数式编程风格引入到Java中。其实简单来说可以把Stream理解为MapRece,当然Google的MapRece的灵感也是来自函数式编程。她其实是一连串支持连续、并行聚集操作的元素。从语法上看,也很像linux的管道、或者链式编程,代码写起来简洁明了,非常酷帅!
八、Date/Time API (JSR 310)
Java 8新的Date-Time API (JSR 310)受Joda-Time的影响,提供了新的java.time包,可以用来替代
java.util.Date和java.util.Calendar。一般会用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration这些类,对于时间日期的改进还是非常不错的。
九、JavaScript引擎Nashorn
Nashorn允许在JVM上开发运行JavaScript应用,允许Java与JavaScript相互调用。
十、Base64
在Java 8中,Base64编码成为了Java类库的标准。Base64类同时还提供了对URL、MIME友好的编码器与解码器。
除了这十大新特性之外,还有另外的一些新特性:
更好的类型推测机制:Java 8在类型推测方面有了很大的提高,这就使代码更整洁,不需要太多的强制类型转换了。
编译器优化:Java 8将方法的参数名加入了字节码中,这样在运行时通过反射就能获取到参数名,只需要在编译时使用-parameters参数。
并行(parallel)数组:支持对数组进行并行处理,主要是parallelSort()方法,它可以在多核机器上极大提高数组排序的速度。
并发(Concurrency):在新增Stream机制与Lambda的基础之上,加入了一些新方法来支持聚集操作。
Nashorn引擎jjs:基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码。
类依赖分析器jdeps:可以显示Java类的包级别或类级别的依赖。
JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)。
㈦ Java8的特性有哪些
1、函数式接口
Java 8 引入的一个核心概念是函数式接口(Functional Interfaces)。通过在接口里面添加一个抽象方法,这些方法可以直接从接口中运行。如果一个接口定义个唯一一个抽象方法,那么这个接口就成为函数式接口。同时,引入了一个新的注解:@FunctionalInterface。可以把他它放在一个接口前,表示这个接口是一个函数式接口。这个注解是非必须的,只要接口只包含一个方法的接口,虚拟机会自动判断,不过最好在接口上使用注解 @FunctionalInterface 进行声明。在接口中添加了 @FunctionalInterface 的接口,只允许有一个抽象方法,否则编译器也会报错。
java.lang.Runnable 就是一个函数式接口。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
2、Lambda 表达式
函数式接口的重要属性是:我们能够使用 Lambda 实例化它们,Lambda 表达式让你能够将函数作为方法参数,或者将代码作为数据对待。Lambda 表达式的引入给开发者带来了不少优点:在 Java 8 之前,匿名内部类,监听器和事件处理器的使用都显得很冗长,代码可读性很差,Lambda 表达式的应用则使代码变得更加紧凑,可读性增强;Lambda 表达式使并行操作大集合变得很方便,可以充分发挥多核 CPU 的优势,更易于为多核处理器编写代码;
Lambda 表达式由三个部分组成:第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。语法如下:
1. 方法体为表达式,该表达式的值作为返回值返回。
(parameters) -> expression
2. 方法体为代码块,必须用 {} 来包裹起来,且需要一个 return 返回值,但若函数式接口里面方法返回值是 void,则无需返回值。
(parameters) -> { statements; }
例如,下面是使用匿名内部类和 Lambda 表达式的代码比较。
下面是用匿名内部类的代码:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("Helllo Lambda in actionPerformed");
}
});
下面是使用 Lambda 表达式后:
button.addActionListener(
\\actionPerformed 有一个参数 e 传入,所以用 (ActionEvent e)
(ActionEvent e)->
System.out.print("Helllo Lambda in actionPerformed")
);
上面是方法体包含了参数传入 (ActionEvent e),如果没有参数则只需 ( ),例如 Thread 中的 run 方法就没有参数传入,当它使用 Lambda 表达式后:
Thread t = new Thread(
\\run 没有参数传入,所以用 (), 后面用 {} 包起方法体
() -> {
System.out.println("Hello from a thread in run");
}
);
通过上面两个代码的比较可以发现使用 Lambda 表达式可以简化代码,并提高代码的可读性。
为了进一步简化 Lambda 表达式,可以使用方法引用。例如,下面三种分别是使用内部类,使用 Lambda 表示式和使用方法引用方式的比较:
//1. 使用内部类
Function<Integer, String> f = new Function<Integer,String>(){
@Override
public String apply(Integer t) {
return null;
}
};
//2. 使用 Lambda 表达式
Function<Integer, String> f2 = (t)->String.valueOf(t);
//3. 使用方法引用的方式
Function<Integer, String> f1 = String::valueOf;
要使用 Lambda 表达式,需要定义一个函数式接口,这样往往会让程序充斥着过量的仅为 Lambda 表达式服务的函数式接口。为了减少这样过量的函数式接口,Java 8 在 java.util.function 中增加了不少新的函数式通用接口。例如:
Function<T, R>:将 T 作为输入,返回 R 作为输出,他还包含了和其他函数组合的默认方法。
Predicate<T> :将 T 作为输入,返回一个布尔值作为输出,该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(与、或、非)。
Consumer<T> :将 T 作为输入,不返回任何内容,表示在单个参数上的操作。
例如,People 类中有一个方法 getMaleList 需要获取男性的列表,这里需要定义一个函数式接口 PersonInterface:
interface PersonInterface {
public boolean test(Person person);
}
public class People {
private List<Person> persons= new ArrayList<Person>();
public List<Person> getMaleList(PersonInterface filter) {
List<Person> res = new ArrayList<Person>();
persons.forEach(
(Person person) ->
{
if (filter.test(person)) {//调用 PersonInterface 的方法
res.add(person);
}
}
);
return res;
}
}
为了去除 PersonInterface 这个函数式接口,可以用通用函数式接口 Predicate 替代如下:
class People{
private List<Person> persons= new ArrayList<Person>();
public List<Person> getMaleList(Predicate<Person> predicate) {
List<Person> res = new ArrayList<Person>();
persons.forEach(
person -> {
if (predicate.test(person)) {//调用 Predicate 的抽象方法 test
res.add(person);
}
});
return res;
}
}
3、接口的增强
Java 8 对接口做了进一步的增强。在接口中可以添加使用 default 关键字修饰的非抽象方法。还可以在接口中定义静态方法。如今,接口看上去与抽象类的功能越来越类似了。
默认方法
Java 8 还允许我们给接口添加一个非抽象的方法实现,只需要使用 default 关键字即可,这个特征又叫做扩展方法。在实现该接口时,该默认扩展方法在子类上可以直接使用,它的使用方式类似于抽象类中非抽象成员方法。但扩展方法不能够重载 Object 中的方法。例如:toString、equals、 hashCode 不能在接口中被重载。
例如,下面接口中定义了一个默认方法 count(),该方法可以在子类中直接使用。
public interface DefaultFunInterface {
//定义默认方法 countdefault int count(){
return 1;
}
}
public class SubDefaultFunClass implements DefaultFunInterface {
public static void main(String[] args){
//实例化一个子类对象,改子类对象可以直接调用父接口中的默认方法 count
SubDefaultFunClass sub = new SubDefaultFunClass();
sub.count();
}
}
静态方法
在接口中,还允许定义静态的方法。接口中的静态方法可以直接用接口来调用。
例如,下面接口中定义了一个静态方法 find,该方法可以直接用 StaticFunInterface .find() 来调用。
public interface StaticFunInterface {public static int find(){
return 1;
}
}
public class TestStaticFun {
public static void main(String[] args){
//接口中定义了静态方法 find 直接被调用
StaticFunInterface.fine();
}
}