本文主要是介绍第七章-2·集合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
集合
集合类概述
集合与数组一样,数组是实现大量同类型数据存储的有利工具,但具有局限性。
其一,定义后的数组长度不可变
其二,不适合进行大量的插入,删除操作
因此需要有不定长的容器存放数据,即集合,也称容器
集合分类
按集合的存储结构
- 单列集合-----Collection
- 双列集合-----Map
两类集合的特点
- Collection:单列集合类的根接口(顶级接口),规定了逐一存放数据。List,Set是继承Collection的两个重要接口。List存放的元素是有序可以重复的,Set存放的元素是无序且不可以重复的。
- List接口:线性表,是可重复集合,并且有序
- Set接口:不可重复的集合,大部分实现类是无序的
- Map:双列集合的根接口,存放数据是一对一对的键值对。一个key对应一个value,其中key是无序且不可以重复的,value是有序且可以重复的。
键值对
- 键(Key)
- 唯一的,可以确保在检索或访问某个特定数据项时不会发生混淆
- 值(Value)
- 可以是任何类型的数据,通过键值对的方式,我们可以存储复杂的数据结构并将数据项关联起来
Collection接口的方法
检查获取元素
- int size():返回此集合中的元素个数
- boolean isEmpty():检查集合是否为空
- boolean contains(Object obj):检查集合是否包含指定的元素
- **boolean containsAll(Collection c)😗*检查集合是否包含指定参数集合中的所有元素
添加元素
- **boolean add(E obj)😗*将指定的元素添加到集合中。如果添加成功,则返回 true;如果集合不支持添加操作或添加失败(例如,由于重复值不允许),则返回 false
- **boolean addAll(Collection c)😗*将指定集合中的所有元素添加到当前集合中。如果添加成功,则返回 true;否则返回 false
删除元素:
- **boolean remove(Object obj)😗*从集合中移除指定的元素(如果存在)。返回被移除的元素是否成功移除的标志(true 或 false)
- **void clear:**清空集合内容(元素设置为null),容器size设置为0
- **removeAll(Collection c)😗*移除此集合中那些包含在指定参数集合中所有元素
- **boolean retainAll(Collection c)😗*只保留当前集合中与指定集合相交的元素,移除其他所有元素。返回被保留元素的数量的标志(true 或 false)
遍历元素:
- **Iterator iterator()😗*返回此集合中的元素的迭代器,用于遍历集合中的元素,通过迭代器可以逐个访问集合中的元素
- **Object[] to Array()😗*返回包含此Collection中所有元素的数组
List接口
java.util.List接口,继承自Collection.
List集合是可重复集,并且有序,提供了一套可以通过索引下标操作元素的方法
常用实现类
- java.util.ArrayList:内部使用数组实现,查询性能更好
- java.util.LinkedList:内部使用双项链表实现,首尾增删元素性能更好
常用方法
- 插入元素:
void add(int index, E element)
:在指定的位置插入指定的元素。
- 获取元素:
E get(int index)
:返回列表中指定位置的元素。- List subList(int start,int end):获取当前集合中指定范围内的子集。两个参数为开始与结束的下标(含头不含尾)
- 删除元素:
E remove(int index)
:移除列表中指定位置的元素,并返回被移除的元素。
- 更新元素:
E set(int index, E element)
:用指定的元素替换列表中指定位置的元素,并返回被替换的元素。注意,此方法不会改变列表中其他元素的索引。
package 集合;import java.util.List;public class 添加插入 {public static void main(String[] args) {/*添加指定元素到集合中*/List list=new java.util.ArrayList();list.add("a");list.add("b");System.out.println(list);//[a, b]/*将指定集合中的所有元素添加到当前集合中*/List list1=new java.util.ArrayList();list1.add("c");list1.add("d");list.addAll(list1);System.out.println(list);//[a, b, c, d]/*在指定的位置插入指定的元素*/list.add(2,"e");System.out.println(list);//[a, b, e, c, d]}
}
package 集合;import java.util.ArrayList;
import java.util.List;public class 检查获取 {public static void main(String[] args) {/*检查获取集合中的元素*/List list=new ArrayList();list.add("1");list.add("2");list.add("3");list.add("4");list.add("5");System.out.println(list);//[1, 2, 3, 4, 5]/*返回列表中指定位置的元素*/System.out.println(list.get(2));//3/*返回列表的长度*/System.out.println(list.size());//5/*检查集合是否为空*/System.out.println(list.isEmpty());//false/*检查集合是否包含指定的元素*/System.out.println(list.contains("3"));//true}}
package 集合;import java.util.List;public class 更新 {public static void main(String[] args) {/*更新元素*/List list = new java.util.ArrayList();list.add("1");list.add("2");list.add("3");list.add("4");list.add("5");list.set(0,"a");System.out.println(list);//[a, 2, 3, 4, 5]}
}
package 集合;import java.util.List;public class 删除 {public static void main(String[] args) {/*删除集合中的元素*/List list = new java.util.ArrayList();list.add("a");list.add("b");list.add("c");list.add("d");list.add("e");/*从集合中移除指定的元素(如果存在)。返回被移除的元素是否成功移除的标志(true 或 false)*/System.out.println("删除的元素是:"+list.remove(1));//删除的元素是:bSystem.out.println(list);//[a, c, d, e]/*清空集合内容,元素设置为null,容器size设置为0*/list.clear();System.out.println(list);//[]/*移除此集合中那些包含在指定参数集合中所有元素*/list.removeAll(list);System.out.println(list);//[]}
}
package 集合;import java.util.ArrayList;
import java.util.List;public class 获取集合中指定内的子集 {public static void main(String[] args) {List<Integer> list = new ArrayList<>();for(int i=0;i<10;i++){list.add(i);}System.out.println(list);//获取3-7这部分List<Integer> subList = list.subList(3,8);System.out.println(subList);//将子集每个元素扩大10倍for(int i=0;i<subList.size();i++){subList.set(i,subList.get(i) * 10);}//[30,40,50,60,70]System.out.println(subList);/*对子集元素的操作就是对原集合对应元素的操作*/System.out.println(list);//删除list集合中的2-8list.subList(2,9).clear();System.out.println(list);}
}
HashSet
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode()值,然后根据hashCode()值决定该对象在HashSet中的存储位置
特点
- 不能保证元素的排序顺序
- 不可重复
- 不是线程安全的
- **boolean add(E e):**尝试将指定元素添加到 Set 中。如果添加成功(即元素尚未存在于 Set 中),则返回 true;否则返回 false。这是 Set 不允许重复元素特性的体现。
- **boolean remove(Object o):**从 Set 中移除指定元素(如果存在)。成功移除后返回 true,否则返回 false。这也是继承自 Collection 接口的方法,但由于 Set 的无重复元素特性,此方法的行为略有不同。
- **boolean contains(Object o):**检查 Set 是否包含指定元素。如果包含则返回 true,否则返回 false。这也是继承自 Collection 接口的方法
- 判断Set两个元素 是否相等的标准方法 :equals(Object obj)和生成 Set 的哈希码的方法 hashCode()
- 如果两个对象通过equals()方法返回true,这两个对象的hashCode值也应该相同
package 集合;import collection.Point;/*表示二维坐标点的类*/import java.util.Collection;
import java.util.HashSet;public class 判断集合重复 {public static void main(String[] args) {//添加Collection c = new HashSet();c.add(new Point(1,2));c.add(new Point(3,4));c.add(new Point(5,6));c.add(new Point(7,8));c.add(new Point(1,2));System.out.println(c);/*boolean contains(Object o)判断当前集合是否包含给定元素,这里判断的依据是给定元素是否与集合现有元素存在equals比较为true的情况。*/Point p = new Point(1,2);boolean contains = c.contains(p);System.out.println("包含:"+contains);/*remove用来从集合中删除给定元素,删除的也是与集合中equals比较为true的元素。注意,对于可以存放重复元素的集合而言,只删除一次。*/c.remove(p);System.out.println(c);}
}
遍历
Collection提供了统一的遍历集合方式:迭代器模式
语法:
Iterator iterator()
- 该方法会获取一个用于遍历当前集合元素的迭代器.
- java.util.Iterator接口
- 迭代器接口,定义了迭代器遍历集合的相关操作.
- 不同的集合都实现了一个用于遍历自身元素的迭代器实现类,我们无需记住它们的名字,用多态的角度把他们看做为Iterator即可
- 迭代器遍历集合遵循的步骤为:问,取,删.其中删除元素不是必要操作
增强for
DK5之后推出了一个特性:增强型for循环
- 也称为新循环,使得我们可以使用相同的语法遍历集合或数组
- 语法
for(元素类型 变量名 : 集合或数组){循环体
}
package 集合;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;public class 遍历 {public static void main(String[] args) {List list=new ArrayList();list.add("a");list.add("1");list.add("2");list.add("3");list.add("4");list.add("5");System.out.println(list);//[a, 1, 2, 3, 4, 5]/*返回此集合中的元素的迭代器,用于遍历集合中的元素,通过迭代器可以逐个访问集合中的元素*/Iterator a=list.iterator();//获取迭代器while (a.hasNext()){/*boolean hasNext()判断集合是否还有元素可以遍历*//*E next()获取集合下一个元素(第一次调用时就是获取第一个元素,以此类推)*/System.out.print(a.next());//a12345}/*增强for遍历* 语法:* for(元素类型 变量名 : 集合或数组){循环体
}*/System.out.println();for (Object o:list){System.out.print(o);//a12345}/*Object[] to Array():返回包含此Collection中所有元素的数组*/System.out.println();Object[] objects = list.toArray();System.out.println(Arrays.toString(objects));//[a, 1, 2, 3, 4, 5]());}
}
泛型
JDK5之后推出的另一个特性:泛型
泛型也称为参数化类型,允许我们在使用一个类时指定它当中属性,方法参数或返回值的类型
- 泛型在集合中被广泛使用,用来指定集合中的元素类型.
- 有泛型支持的类在使用时若不指定泛型的具体类型则默认为原型Object
通俗易懂
泛型就是提前给集合定义一种数据类型
package 集合;
import java.util.Arrays;
import java.util.Iterator;
public class 泛型 {public static void main(String[] args) {String[] c = {"one","two","three","four","five"};//迭代器遍历//迭代器也支持泛型,指定的与其遍历的集合指定的泛型一致即可Iterator<String> it = Arrays.stream(c).iterator();//泛型while(it.hasNext()){//编译器编译代码时会根据迭代器指定的泛型补充造型代码String str = it.next();//获取元素时无需在造型System.out.println(str);}/* //新循环遍历for(String str : c){System.out.println(str);}*/}
}
TreeSet
TreeSet是SortedSes接口的实现类,TreeSet可以确保集合元素处于排序状态
支持排序的两种方法
- 自然排序(默认排序)
package 集合;import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;public class treeSet {public static void main(String[] args) {Set<Integer> a = new TreeSet<>();/*** TreeSet* 自然排序*/a.add(2);a.add(5);a.add(8);a.add(1);a.add(4);System.out.println(a);//12458//使用迭代器,遍历Iterator<Integer> a1=a.iterator();while(a1.hasNext()){System.out.print(a1.next());}}
}
- 定制排序
- 需要在创建集合对象时,提供一个Compartor接口的实现类对象。由该Compartor对象负责集合元素的排序逻辑
集合与数组的转换
集合转换为数组
Collection提供了一个方法:toArray,可以将当前集合转换为一个数组
package collection;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 集合转换为数组* Collection提供了方法toArray可以将当前集合转换为一个数组*/
public class CollectionToArrayDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("one");list.add("two");list.add("three");list.add("four");list.add("five");System.out.println(list);// Object[] array = list.toArray();/*重载的toArray方法要求传入一个数组,内部会将集合所有元素存入该数组后将其返回(前提是该数组长度>=集合的size)。如果给定的数组长度不足,则方法内部会自行根据给定数组类型创建一个与集合size一致长度的数组并将集合元素存入后返回。*/String[] array = list.toArray(new String[list.size()]);System.out.println(array.length);System.out.println(Arrays.toString(array));}
}
/*
[one, two, three, four, five]
5
[one, two, three, four, five]
*/
数组转换为List集合
数组的工具类Arrays提供了一个静态方法asList(),可以将一个数组转换为一个List集合
package collection;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 数组转换为List集合* 数组的工具类Arrays提供了一个静态方法asList,可以将数组转换为一个List集合。*/
public class ArrayToListDemo {public static void main(String[] args) {String[] array = {"one","two","three","four","five"};System.out.println(Arrays.toString(array));List<String> list = Arrays.asList(array);System.out.println(list);list.set(1,"six");System.out.println(list);//数组跟着改变了。注意:对数组转换的集合进行元素操作就是对原数组对应的操作System.out.println(Arrays.toString(array));/*由于数组是定长的,因此对该集合进行增删元素的操作是不支持的,会抛出异常:java.lang.UnsupportedOperationException*/
// list.add("seven");/*若希望对集合进行增删操作,则需要自行创建一个集合,然后将该集合元素导入。*/
// List<String> list2 = new ArrayList<>();
// list2.addAll(list);/*所有的集合都支持一个参数为Collection的构造方法,作用是在创建当前集合的同时包含给定集合中的所有元素*/List<String> list2 = new ArrayList<>(list);System.out.println("list2:"+list2);list2.add("seven");System.out.println("list2:"+list2);}
}
/*
[one, two, three, four, five]
[one, two, three, four, five]
[one, six, three, four, five]
[one, six, three, four, five]
list2:[one, six, three, four, five]
list2:[one, six, three, four, five, seven]
*/
集合的排序
java.util.Collections类
Collections是集合的工具类,里面定义了很多静态方法用于操作集合
Collections.sort(List list)方法
可以对List集合进行自然排序(从小到大)
package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/*** 集合的排序* 集合的工具类:java.util.Collections提供了一个静态方法sort,可以对List集合进行自然排序*/
public class SortListDemo1 {public static void main(String[] args) {List<Integer> list = new ArrayList<>();Random random = new Random();for(int i=0;i<10;i++){list.add(random.nextInt(100));}System.out.println(list);Collections.sort(list);System.out.println(list);}
}
排序自定义类型元素
package collection;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*** 排序自定义类型元素*/
public class SortListDemo2 {public static void main(String[] args) {List<Point> list = new ArrayList<>();list.add(new Point(3,5));list.add(new Point(7,9));list.add(new Point(1,1));list.add(new Point(8,3));list.add(new Point(2,6));System.out.println(list);/*编译不通过的原因:Collections.sort(List list)该方法要求集合中的元素类型必须实现接口:Comparable,该接口中有一个抽象方法compareTo,这个方法用来定义元素之间比较大小的规则.所以只有实现了该接口的元素才能利用这个方法比较出大小进而实现排序操作.*/Collections.sort(list);//编译不通过 compare比较 comparable可以比较的System.out.println(list);}
}
重载的Collections.sort(List list,Comparator c)方法
package collection;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** 排序自定义类型元素*/
public class SortListDemo2 {public static void main(String[] args) {List<Point> list = new ArrayList<>();list.add(new Point(3,5));list.add(new Point(7,9));list.add(new Point(1,1));list.add(new Point(8,3));list.add(new Point(2,6));System.out.println(list);/*编译不通过的原因:Collections.sort(List list)该方法要求集合中的元素类型必须实现接口:Comparable,该接口中有一个抽象方法compareTo,这个方法用来定义元素之间比较大小的规则.所以只有实现了该接口的元素才能利用这个方法比较出大小进而实现排序操作.当我们调用某个API时,它反过来要求我们为其修改其他额外的代码时就是侵入性.侵入性不利于程序后期的维护,应当在实际开发中尽量避免.*/
// Collections.sort(list);//编译不通过 compare比较 comparable可以比较的/*Collections.sort(List list,Comparator c)重载的sort方法要求我们再传入一个Comparator"比较器",该比较器用来为集合元素临时定义一种比较规则,从而将List集合中的元素通过该比较器比较大小后进行排序.Comparator是一个接口,实际应用中我们需要实现该接口为集合元素提供比较规则.*/Comparator<Point> c = new Comparator<Point>() {/*** compare方法用来定义两个参数o1,o2的大小关系* 返回值用来表示o1与o2的大小关系* 当返回值>0时,应当表示的含义是o1>o2* 当返回值<0时,表示o1<o2* 当返回值=0时,表示o1与o2相等*/public int compare(Point o1, Point o2) {int olen1 = o1.getX()*o1.getX()+o1.getY()*o1.getY();int olen2 = o2.getX()*o2.getX()+o2.getY()*o2.getY();return olen1-olen2;}};Collections.sort(list,c);System.out.println(list);}
}
最终没有入侵性的写法
package collection;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** 排序自定义类型元素*/
public class SortListDemo2 {public static void main(String[] args) {List<Point> list = new ArrayList<>();list.add(new Point(3,5));list.add(new Point(7,9));list.add(new Point(1,1));list.add(new Point(8,3));list.add(new Point(2,6));System.out.println(list);/*编译不通过的原因:Collections.sort(List list)该方法要求集合中的元素类型必须实现接口:Comparable,该接口中有一个抽象方法compareTo,这个方法用来定义元素之间比较大小的规则.所以只有实现了该接口的元素才能利用这个方法比较出大小进而实现排序操作.当我们调用某个API时,它反过来要求我们为其修改其他额外的代码时就是侵入性.侵入性不利于程序后期的维护,应当在实际开发中尽量避免.*/
// Collections.sort(list);//编译不通过 compare比较 comparable可以比较的/*Collections.sort(List list,Comparator c)重载的sort方法要求我们再传入一个Comparator"比较器",该比较器用来为集合元素临时定义一种比较规则,从而将List集合中的元素通过该比较器比较大小后进行排序.Comparator是一个接口,实际应用中我们需要实现该接口为集合元素提供比较规则.*/
// Comparator<Point> c = new Comparator<Point>() {
// /**
// * compare方法用来定义两个参数o1,o2的大小关系
// * 返回值用来表示o1与o2的大小关系
// * 当返回值>0时,应当表示的含义是o1>o2
// * 当返回值<0时,表示o1<o2
// * 当返回值=0时,表示o1与o2相等
// */
// public int compare(Point o1, Point o2) {
// int olen1 = o1.getX()*o1.getX()+o1.getY()*o1.getY();
// int olen2 = o2.getX()*o2.getX()+o2.getY()*o2.getY();
// return olen1-olen2;
// }
// };
// Collections.sort(list,c);Collections.sort(list,new Comparator<Point>() {public int compare(Point o1, Point o2) {int olen1 = o1.getX()*o1.getX()+o1.getY()*o1.getY();int olen2 = o2.getX()*o2.getX()+o2.getY()*o2.getY();return olen1-olen2;}});System.out.println(list);}
}
排序字符串
java中提供的类,如:String,包装类都实现了Comparable接口,但有时候这些比较规则不能满足我们的排序需求时,同样可以临时提供一种比较规则来进行排序.
package collection;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;public class SortListDemo3 {public static void main(String[] args) {List<String> list = new ArrayList<>();
// list.add("Tom");
// list.add("jackson");
// list.add("rose");
// list.add("jill");
// list.add("ada");
// list.add("hanmeimei");
// list.add("lilei");
// list.add("hongtaoliu");
// list.add("Jerry");list.add("传奇老师");list.add("王克晶");list.add("刘桑");System.out.println(list);//按照字符多少排序
// Collections.sort(list);
// Collections.sort(list, new Comparator<String>() {
// public int compare(String o1, String o2) {return o1.length()-o2.length();
// return o2.length()-o1.length();//反过来减就是降序
// }
// });Collections.sort(list,(o1,o2)->o2.length()-o1.length());System.out.println(list);}
}
lambda表达式
Lambda表达式-JDK8之后推出的新特性
-
语法:
(参数列表)->{方法体 }
-
当使用匿名内部类创建时,如果实现的接口只有一个抽象方法,则可以使用lambda表达
式代替,使代码更简洁优雅。
-
在java中可以使用lambda表达式代替匿名内部类创建所需要实现的接口时,该接口上都有一个注解:@FunctionalInterface
lambda创建比较器用于排序集合
public class LambdaDemo {public static void main(String[] args) {//自定义比较器的匿名内部类写法Comparator<String> c1 = new Comparator<String>() {public int compare(String o1, String o2) {return o1.length()-o2.length();}};//使用lambda表达式//lambda表达式就是省去了匿名内部类创建是接口与方法名部分Comparator<String> c2 = (String o1, String o2)->{return o1.length()-o2.length();};//lambda表达式可以忽略参数的类型Comparator<String> c3 = (o1,o2)->{return o1.length()-o2.length();};//如果方法中只有一句代码时,该方法体的"{}"可以忽略不写//如果这句代码含有return关键字时,也要一同忽略returnComparator<String> c4 = (o1,o2)->o1.length()-o2.length();List<String> list = new ArrayList<>();list.add("王克晶");list.add("传奇老师");list.add("刘桑");//lambda表达式实际上是编译器认可的,最终会被改回为内部类方式创建//源代码中使用lambda可以更突出重点-原匿名内部类中重写方法的逻辑。
// Collections.sort(list,(o1,o2)->o1.length()-o2.length());/*JDK8之后,List集合自己推出了一个sort方法,可以排序自身元素并且需要传入一个比较器来定义比较规则。*/list.sort((o1,o2)->o1.length()-o2.length());System.out.println(list);}
}
基于lambda表达式的集合遍历
package collection;import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;/*** JDK8之后,java在集合Collection接口中添加了一个用于遍历集合元素的forEach* 方法。可以基于lambda表达式遍历集合元素。*/
public class ForEachDemo {public static void main(String[] args) {Collection<String> c = new ArrayList<>();c.add("one");c.add("two");c.add("three");c.add("four");c.add("five");//新循环方式(迭代器方式)for(String e : c){System.out.println(e);}//tips:当lambda中只有一个参数时,参数列表的"()"可以忽略不写c.forEach(e->System.out.println(e));/*JDK8中出现的lambda表达式的变种写法:方法引用对象::方法当lambda表达式的参数与方法体中调用方法的参数一致时例如:(e)->System.out.println(e);那么就可以写作:System.out::println;对象::方法现在以了解为主即可*/c.forEach(System.out::println);}
}
Map接口
双列集合的根接口**,存放数据是一对一对的键值对。一个key对应一个value,其中key是无序且不可以重复的,**value是有序且可以重复的。
package 集合;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class map {public static void main(String[] args) {Map<String,Integer> a=new HashMap<>();/*添加*/a.put("a",1);a.put("b",2);a.put("c",3);System.out.println(a);//{a=1, b=2, c=3}/*根据key取值*/System.out.println(a.get("c"));//3/*删除*/a.remove("b");System.out.println(a);//{a=1, c=3}/*集合的长度*/System.out.println(a.size());//2/*判断当前集合是否包含指定的key*/System.out.println(a.containsKey("a"));//true/*判断当前集合是否包含指定的value*/System.out.println(a.containsValue(7));//false/*遍历*/Set<String> keys=a.keySet();System.out.println(keys);//获取key的集合a.values();System.out.println(a.values());//获取所有value值/*遍历for*/for (String key:keys){System.out.println("key:"+key+","+"value:"+a.get(key));//a 1 c 3}}
}
这篇关于第七章-2·集合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!