标签:accept util each 实现 删除元素 并行 ram object 使用方法
目录
Collection接口是List、Set、Queue接口的父接口,该接口里定义了即可以用于操作Set集合,也可以用于操作List和Queue集合。Collection接口里定义操作集合元素的方法:
★boolean add(Object o):该方法用于向集合中添加一个元素。如果集合对象被添加操作改变了,则返回true。
★boolean addAll(Collection c):该方法把集合c里所有元素添加到指定集合里。如果集合对象被添加操作改变了,则返回true。
★void clear():清除集合中的所有元素,将集合长度变为0.
★boolean contains(Object o):返回集合中是否包含指定元素。
★boolean containsAll(Object o):返回集合中是否包含集合c里的所有元素。
★boolean isEmpty():返回集合是否为空。当集合长度为0时返回true,否则返回false。
★boolean iterator():返回一个Iterator对象,用于遍历集合的元素
★boolean remove(Object o):删除集合中指定元素o,当即和中包含一个或多个元素o时,该方法只删除第一个满足符合条件的元素,该方法返回true。
★boolean removeAll(Collection c):从集合中删除集合c里的所有元素,如果删除一个或多个元素,该方法返回true。
★boolean retiaiNALll(Collection c):从集合删除c里不包含的元素,如果该操作改变了调用该方法的集合,则返回true。
★int size():该方法返回集合中元素个数
★Object[] toArray():该方法将集合转换为一个数组,所有集合元素变成对于的数组元素。
更多方法参看java.util.Collection的API文档
程序实例:
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashSet;
public class CollectionTest
{
public static void main(String[] args)
{
//List集合测试
var c=new ArrayList();
//集合是否为空
System.out.println(c.isEmpty());
//添加元素
c.add("孙悟空");
//虽然Java集合中保存的是对象,但Java支持自动装箱
c.add(6);
System.out.println("集合中的元素个数:"+c.size());//2
//删除元素
c.remove(1);//对于删除整数对象,只能指定它的索引值
System.out.println("集合中的元素个数:"+c.size());//1
//判断是否包含指定字符串
System.out.println(c.contains("孙悟空"));//true
c.add("轻量级Java EE企业级实战");
System.out.println("c集合中的元素"+c);
//Set集合测试
var books=new HashSet();
books.add("轻量级Java EE企业级实战");
books.add("疯狂Java讲义");
//c集合是否完全包含books集合
System.out.println("c集合是否完全包含books集合:"+c.containsAll(books));
//从c集合中减去books集合中的元素
c.removeAll(books);
System.out.println("集合c的元素:"+c);//集合c的元素:[孙悟空]
//删除集合c中的所有元素
c.clear();
System.out.println("集合c的元素:"+c);
}
}
---------- 运行Java捕获输出窗 ----------
true
集合中的元素个数:2
集合中的元素个数:1
true
c集合中的元素[孙悟空, 轻量级Java EE企业级实战]
c集合是否完全包含books集合:false
集合c的元素:[孙悟空]
集合c的元素:[]
输出完成 (耗时 0 秒) - 正常终止
上面创建了两个Collection对象,一个是集合books集合(HashCode集合),一个是c集合(ArrayList)。虽然他们的实现类不同,当它们都是Collection接口的实现类,因此继承了Collection接口中操作数组的方法。
当使用System.out.println()打印集合时,将输出[ele1,ele2,ele3...]的形式,这是因为所有Collection实现类都重写toString()方法,带方法可以一次性地输出集合中的所有元素。
注意:在传统模式下,把一个对象“丢进”集合中后,集合会忘记这个对象的类型——也就是说系统把所有集合元素都当作Object类型。从Java 1.5以后,这种状态得到了改进:可以使用泛型来限制集合里的元素类型,并让集合记住所有元素的类型。
Java 11为Collecton新增了一个toArray(IntFunction)方法,该方法的主要目的就是为了使用泛型。对于传统的toArray()方法而言,不管Collection本身是否使用泛型,toArray()总是返回Object[];但改进后toArray(IntFunction)方法不同,当Collection使用泛型时,toArray(IntFunction)可以返回特定类型的数组。
例如:
//该Collection使用泛型,指定它的集合元素都是String
var strColl=List.of("Java","Kotlin","Swift","Python");
//toArray()方法参数就是一个Lambda表达式,代表IntFunction对象
//此时toArray()方法返回值类型是String[], 二不是Object[]
String[] sa=strColl.toArray(String::new);//调用String类的构造器
System.out.println(Arrays.toString(sa));
Java 8为Iterator接口新增了一个forEach(Consumer action)默认方法,该方法所需参数是一个函数式接口,而Iterable接口是Collection接口的父接口,因此Collection方法可以直接调用该方法。
当程序调用Iteratable的forEach(Comsumer action)遍历集合元素时,程序会依次将集合元素传给Consumer的accept(T,t)方法(该接口中唯一的抽象方法。)正是因为Comsumer接口是函数式接口,因此可以使用Lambda表达式来遍历该集合的元素。
程序实例:
import java.util.Collection;
import java.util.HashSet;
public class CollectionEach
{
public static void main(String[] args)
{
//创建一个集合Set
var books=new HashSet();
books.add("三国演义");
books.add("西游记");
books.add("红楼梦");
books.add("水浒传");
books.forEach(obj->System.out.println("迭代集合元素:"+obj));
}
}
---------- 运行Java捕获输出窗 ----------
迭代集合元素:水浒传
迭代集合元素:三国演义
迭代集合元素:红楼梦
迭代集合元素:西游记
输出完成 (耗时 0 秒) - 正常终止
Iterator接口也是Java集合框架的成员,但它与Collection系列、Map系列集合不一样:Collection和Map系列集合主要用于盛装其他对象,而Iterable则主要用于遍历(即迭代访问)Collection集合中的元素,Iterator对象也被称为迭代器。
Iterator向程序遍历Collection系列集合元素提供了统一的编程接口。Iterator接口里定义了4个方法:
★boolean hasNext():被迭代的集合元素还没有被遍历完,则返回true。
★Object next():返回集合里的下一个元素。
★void remove():删除集合里上一次next方法返回的元素。
★void forEachRemaining(Consumer action):这是Java 8为Iterator新增的方法,该方法可以使用Lambda表达式来遍历集合中的元素。
下面程序示范了如何通过Iterator接口来遍历集合中的元素:
import java.util.HashSet;
public class IteratorTest
{
public static void main(String[] args)
{
//创建集合元素
var books=new HashSet();
books.add("三国演义");
books.add("西游记");
books.add("红楼梦");
books.add("水浒传");
System.out.println(books);//Colletion接口改写toString()方法
//获取books集合对应的迭代器
var it=books.iterator();
while(it.hasNext())
{
//it.next()方法返回的数据类型是Object类型,因此需要强转
var book=(String)it.next();
System.out.println(book);
if(book.equals("红楼梦"))
{
//从集合中删除上一次next()方法返回的元素
it.remove();
}
//对book遍历赋值不会改变集合元素本身
book="测试字符串";
}
System.out.println(books);
}
}
[水浒传, 三国演义, 红楼梦, 西游记]
水浒传
三国演义
红楼梦
西游记
[水浒传, 三国演义, 西游记]
请按任意键继续. . .
Iterator仅用于遍历集合本身,Iterator本身并不提供盛装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。没有集合的Iterator仿佛一个无本之木,没有存在价值。
book="测试字符串";对集合元素没有影响,说明当使用Iterator对集合元素进行迭代时,Iterator并不把集合元素本身传给迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代遍历的值对集合元素本身没有影响。当使用Iterator迭代访问Collection集合元素时,Collection集合里的元素不能被改变,只有通过Iterator的remove()方法删除上一次的next()方法返回的集合元素才可以;否则将会引发java.util.ConcurrentModificationException异常。
import java.util.*;
public class IteratorErrorTest
{
public static void main(String[] args)
{
// 创建集合、添加元素的代码与前一个程序相同
var books = new HashSet();
books.add("轻量级Java EE企业应用实战");
books.add("疯狂Java讲义");
books.add("疯狂Android讲义");
// 获取books集合对应的迭代器
var it = books.iterator();
while (it.hasNext())
{
var book = (String) it.next();
System.out.println(book);
if (book.equals("疯狂Android讲义"))
{
// 使用Iterator迭代过程中,不可修改集合元素,下面代码引发异常
books.remove(book);
}
}
}
}
★void forEachRemaining(Consumer action):这是Java 8为Iterator新增的方法,该方法可以使用Lambda表达式来遍历集合中的元素。与Collection接口中的forEach()方法相似。
Java 8 为Iterator新增了一个forEachRemaining(Consumer action)方法,该方法所需的Consumer参数同样也是函数式接口。当程序员调用Iterator的forEachRemianing(Consumer action)遍历集合元素时,程序将会依次将集合元素传给Comsumer的accept(T t)方法(该接口中的唯一抽象方法):
import java.util.HashSet;
public class IteratorEach
{
public static void main(String[] args)
{
//创建集合元素
var books=new HashSet();
books.add("三国演义");
books.add("西游记");
books.add("红楼梦");
books.add("水浒传");
System.out.println(books);//Colletion接口改写toString()方法
//获取集合的迭代器
var it=books.iterator();
//迭代器的forEachRemaining()方法调用Consumer接口中的accept()方法
it.forEachRemaining(obj->System.out.println(obj));
}
}
[水浒传, 三国演义, 红楼梦, 西游记]
水浒传
三国演义
红楼梦
西游记
请按任意键继续. . .
Java 5提供的foreach循环迭代访问集合的元素更加便捷。
import java.util.ArrayList;
public class ForeachTest
{
public static void main(String[] args)
{
//创建集合list
var l=new ArrayList();
System.out.println(l.isEmpty());
l.add("三国演义");
l.add("西游记");
l.add("水浒传");
l.add("红楼梦");
System.out.println(l);
for(var book:l)
{
System.out.println(book);
}
}
}
true
[三国演义, 西游记, 水浒传, 红楼梦]
三国演义
西游记
水浒传
红楼梦
请按任意键继续. . .
Java 8为Collection集合新增了一个removeIf(Predicate fliter)方法,该方法将会批量删除符合fliter条件的所有元素。该方法需要一个Predicate(谓词)对象作为参数,Predicate也是函数式接口,因此可以使用Lambda表达式作为参数。
Predicate为一个函数式接口,里面唯一的抽象方法:
boolean test?(T t)
Evaluates this predicate on the given argument.
Parameters:
t - the input argument
Returns:
true if the input argument matches the predicate, otherwise false
下面程序示范了使用Predicate来过滤集合:
import java.util.HashSet;
class PredictInit
{
public static void main(String[] args)
{
var books=new HashSet();
books.add("轻量级Java EE企业级应用实战");
books.add("疯狂Java讲义");
books.add("疯狂IOS讲义");
//使用Lambda表达式(目标类型是Predicate)过滤集合
books.removeIf(ele->((String) ele).length()<10);
System.out.println(books);
}
}
---------- 运行Java捕获输出窗 ----------
[轻量级Java EE企业级应用实战]
输出完成 (耗时 0 秒) - 正常终止
假设依然有上面的程序的books集合,如果程序有以下三个统计需求:
1、统计书名中出现“疯狂”字符串的图书数量
2、统计书名中出现“Java”字符串的图书数量
3、统计书名长度大于10的图书数量
如果采用传统的编程(使用正则表达式),则需要执行三次循环,但Predicate只需要一个方法就可以。例如:
import java.util.HashSet;
import java.util.Collection;
import java.util.function.Predicate;
public class PredicateTest
{
public static void main(String[] args)
{
var books=new HashSet();
books.add("轻量级Java EE企业级应用实战");
books.add("疯狂Java讲义");
books.add("疯狂IOS讲义");
//1、统计书名中出现“疯狂”字符串的图书数量
System.out.println(callAll(books,ele->((String) ele).contains("疯狂")));
//2、统计书名中出现“Java”字符串的图书数量
System.out.println(callAll(books,ele->((String) ele).contains("Java")));
//3、统计书名长度大于10的图书数量
System.out.println(callAll(books,ele->((String) ele).length()>10));
}
public static int callAll(Collection books,Predicate fliter)
{
int total=0;
for(var obj:books)
{
//使用Predicate的test()方法判断对象是否满足Predicate指定的条件
if(fliter.test(obj))
{
total++;
}
}
return total;
}
}
---------- 运行Java捕获输出窗 ----------
2
2
1
输出完成 (耗时 0 秒) - 正常终止
Java 8还新增了Stream、IntStream、LongStream、DoubleStream等流式API,这些API接口代表多个支持串行和并行聚集操作的元素。
Stream是一个通用的流接口,而IntStream、LongStream、DoubleStream则代表元素类型为int、long、double的流。
Java 8还未每个流式API提供对应的Builder,例如Stream.Builder、IntStream.Builder、LongStream.Builder、DoubleStream.builder,开发者可以用这些Builder创建对应的流:
独立使用Stream的步骤:
1、使用Stream或XxxStream的Builder()类方法创建该Stream对应的Builder。
2、重复使用Builder的add()方法向该流中添加多个元素
3、调用Builder的build()方法获取对应的流
4、调用Stream的聚集方法。
import java.util.stream.*;
public class IntStreamTest
{
public static void main(String[] args)
{
var is = IntStream.builder()
.add(20)
.add(13)
.add(-2)
.add(18)
.build();
// 下面调用聚集方法的代码每次只能执行一个
//System.out.println("is所有元素的最大值:" + is.max().getAsInt());
// System.out.println("is所有元素的最小值:" + is.min().getAsInt());
// System.out.println("is所有元素的总和:" + is.sum());
// System.out.println("is所有元素的总数:" + is.count());
// System.out.println("is所有元素的平均值:" + is.average());
// System.out.println("is所有元素的平方是否都大于20:"
// + is.allMatch(ele -> ele * ele > 20));
// System.out.println("is是否包含任何元素的平方大于20:"
// + is.anyMatch(ele -> ele * ele > 20));
// 将is映射成一个新Stream,新Stream的每个元素是原Stream元素的2倍+1
var newIs = is.map(ele -> ele * 2 + 1);
// 使用方法引用的方式来遍历集合元素
newIs.forEach(System.out::println); // 输出41 27 -3 37
}
}
上面创建的IntStream,接下来分别多次调用了IntStream的聚集方法执行操作,这样即可获取该流的相关信息。注意上面的方法只能执行一次,因此需要把其他方法注释掉。
Stream提供了大量的方法进行聚集操作,这些方法既可以是中间的(intermediate)、也可是“末端的”(terminal).
1、中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。上面的Map()方法就是一个中间方法,中间方法返回值是另外一个流。
2、末端方法:末端方法是对流的最终操作。当对某个流执行末端方法后,该流将会被“消耗”且不可再用。上面的sun()、count()、average()等方法是末端方法。
流的方法具有两个特征
1、有状态的方法:这种方法会增加流的一些属性,比如元素的唯一性、元素的最大数量、保证元素以排序方式被处理等。有状态方法往往需要更大的性能开销。
2、短路方法:短路方法可以尽早结束对流的操作,不必检查所有元素。
简单介绍一下Stream中间方法:
★fliter(Predicate predicate):过滤掉Stream流中所有不符合的predicate元素。
★mapToXxx(ToXxxFunction mapper):使用ToXxxFunction对流中的元素执行一对一的转换,该方法返回对流中包含了ToXxxFunction转换生成的所有元素。
★peek(Consumer action):依次对每个元素执行一些操作,该方法返回的流与原有流包含相同的元素。该方法主要用于测试。
★distinct():该方法用于排序流中所有重复的元素(判断元素重复的标准是利用eaquls()比较返回true)。这是一个有状态的方法。
★sorted():该方法用于保证流中的元素在后续访问中处于有序状态。这是一个有状态的方法.
★limit(long maxSize):该方法用于保证对该流的后续访问中最大允许访问元素个数。这是一个有状态的、短路的方法。
下面简单介绍一下Stream流中的末端方法:
★forEach(Consumer action):遍历流中的所有元素,对每个元素执行action。
★toArray():将流中所有元素转换为一个数组。
★reduce():该方法有三个重载版本,都用于通过某种操作来合并流中的元素。
★min():返回流中的所有元素的最小值。
★max():返回流中元素的最大值。
★count():返回流中元素的数量。
★anyMatch(Predicate predicate):判断流中是否至少含有一个元素符合Predicate条件。
★noneMatch(Predicate predicate):判断流中是否所有元素都不符合Predicate条件。
★allMatch(Predicate predicate):判断流中是否所有的元素都满足Predicate条件。
★findFirst():返回流中的第一个元素。
★findAny():返回流中任意一个元素。
Java 8允许使用流式API来操作集合,Collection接口提供了一个stream()默认方法,该方法可返回该集合对应的流,接下来可通过流式API来操作集合元素。
import java.util.HashSet;
public class CollectionStream
{
public static void main(String[] args)
{
//创建一个集合
var books=new HashSet();
books.add("轻量级Java EE企业级应用实战");
books.add("疯狂Java讲义");
books.add("疯狂IOS讲义");
books.add("疯狂Aja讲义");
books.add("疯狂Android讲义");
//统计书名中包含“疯狂”子串的图书数量
System.out.println(books.stream()
.filter(ele->((String) ele).contains("疯狂")).count());
//统计书名中包含“Java”子串的图书数量
System.out.println(books.stream()
.filter(ele->((String) ele).contains("Java")).count());
// 统计书名字符串长度大于10的图书数量
System.out.println(books.stream()
.filter(ele->((String) ele).length() > 10)
.count()); // 输出2
// 先调用Collection对象的stream()方法将集合转换为Stream,
// 再调用Stream的mapToInt()方法获取原有的Stream对应的IntStream
books.stream().mapToInt(ele -> ((String) ele).length())//返回一个新流
// 调用forEach()方法遍历IntStream中每个元素
.forEach(System.out::println);// 输出7 11 17 7 8.Set时无序的
}
}
上面程序最后一段代码先调用Collection对象的stream()方法将集合转换成Stream对象,然后调用Stream对象的mapToInt()方法将其转换为IntStream--这个mapToInt()就是一个中间方法,因此程序可继续调用IntStream的forEach()方法来遍历流中的元素。
7.2 Java 11新增的Collection和Iterator接口
标签:accept util each 实现 删除元素 并行 ram object 使用方法
原文地址:https://www.cnblogs.com/weststar/p/12491531.html