java基础之集合练习题
题目1
请简述集合框架。
集合框架是 Java 中用于存储和操作对象的一组类和接口。它提供了各种数据结构(如列表、集合、映射等)以及操作这些数据结构的方法。Java 集合框架主要包括以下几个核心接口:
- Collection 接口:
Collection
接口是集合框架的根接口,它继承自Iterable
接口,提供了一组基本的方法,用于操作集合中的元素。
- List 接口:
List
接口继承自Collection
接口,表示有序的集合,允许包含重复元素。List
中的元素可以通过索引访问,提供了一系列与索引相关的方法,如get(int index)
和set(int index, E element)
。
- Set 接口:
Set
接口继承自Collection
接口,表示不允许包含重复元素的集合。Set
不保证元素的顺序,实现类可能以任意顺序存储元素。
- Map 接口:
Map
接口表示键值对的集合,每个键都是唯一的。Map
不继承自Collection
接口,因为它主要关注键值对的操作,而不是元素的操作。常用的实现类有HashMap
、TreeMap
和LinkedHashMap
。
- Queue 接口:
Queue
接口表示一个先进先出(FIFO)的队列。常用的实现类有LinkedList
和PriorityQueue
。Java 集合框架提供了丰富的实现类,其中一些常用的包括
ArrayList
、LinkedList
、HashSet
、TreeSet
、HashMap
、TreeMap
等。集合框架的设计目标是提供高性能、灵活性和可读性,并且为程序员提供了丰富的操作集合的方法。这使得在开发中能够方便地使用和管理数据。
题目2
Collection集合统计元素出现次数。
Iterator
是 Java 集合框架中的一个接口,用于遍历集合中的元素。它是集合框架中迭代器模式的一部分,提供了一种统一的方式来访问集合中的元素,而不暴露底层集合的实现细节。
Iterator
接口定义了以下主要方法:
boolean hasNext()
: 判断集合中是否还有下一个元素。
E next()
: 返回集合中的下一个元素,并将迭代器的位置移动到下一个元素。
void remove()
: 从集合中移除通过迭代器最后一次返回的元素(可选操作)。使用
Iterator
的典型模式是通过循环遍历集合中的元素,如下所示:List<String> list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); list.add("Orange"); // 使用 Iterator 迭代器遍历集合 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); System.out.println(element); }
在这个例子中,
list.iterator()
返回一个实现了Iterator
接口的迭代器对象,然后通过while
循环使用hasNext()
和next()
方法遍历集合中的元素。这种迭代方式是安全的,因为它不依赖于底层集合的具体实现。
public class Test01 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.println("a:"+listTest(list, "a"));
System.out.println("b:"+listTest(list, "b"));
System.out.println("c:"+listTest(list, "c"));
System.out.println("xxx:"+listTest(list, "xxx"));
}
//查找list中s出现的次数
public static int listTest(Collection<String> list,String s){
int count = 0;
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
if (iterator.next().equals(s)){
count++;
}
}
return count;
}
}
题目3
定义一个方法,要求此方法把int数组转成存有相同元素的集合(集合里面的元素是Integer),并返回。
public class Test02 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
ArrayList<Integer> arrayList = arrayReve(arr);
System.out.println(arrayList);
}
public static ArrayList<Integer> arrayReve(int[] arr){
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i:arr) {
arrayList.add(i);
}
return arrayList;
}
}
题目4
定义一个集合,并把集合(集合里面的元素是Integer)转成存有相同元素的数组,并将结果输出在控制台。
public class Test03 {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(5);
arrayList.add(4);
arrayList.add(3);
arrayList.add(2);
arrayList.add(1);
Integer[] integer = listReve(arrayList);
for(int i:integer){
System.out.println(i);
}
}
public static Integer[] listReve(ArrayList<Integer> arrayList){
Integer[] integers = new Integer[arrayList.size()];
Iterator<Integer> iterator = arrayList.iterator();
int i = 0;
while (iterator.hasNext()){
integers[i] = iterator.next();
i++;
}
return integers;
}
}
题目5
定义一个方法listTest(ArrayList al, String s),要求使用contains()方法判断al集合里面是否包含s。
public class Test04 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("apple");
arrayList.add("banana");
arrayList.add("orange");
// 测试方法
listTest(arrayList, "banana"); // 输出: true
listTest(arrayList, "grape"); // 输出: false
}
public static void listTest(ArrayList<String> al, String s) {
if (al.contains(s)) {
System.out.println("ArrayList contains " + s);
} else {
System.out.println("ArrayList does not contain " + s);
}
}
}
题目6
定义一个方法listTest(ArrayList al), 要求使用isEmpty()判断al里面是否有元素。
public class Test05 {
public static void main(String[] args) {
//定义集合,添加数据
ArrayList<String> list = new ArrayList<String>();
list.add("1");
System.out.println(listTest(list));
}
public static boolean listTest(ArrayList<String> a1){
Iterator<String> iterator = a1.iterator();
return a1.isEmpty();
}
}
题目7
请简述迭代器的实现原理。
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
题目8
定义一个方法listTest(ArrayList al, Integer s),要求返回s在al里面第一次出现的索引,如果s没出现过返回-1。
public class Test06 {
public static void main(String[] args) {
//定义集合,添加数据
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(listTest(list, 5));
}
public static int listTest(ArrayList<Integer> al, Integer s){
int flag = -1;
int index = 0;
for (int i:al) {
if(i == s){
return index;
}
index++;
}
return flag;
}
}
题目9
产生10个1-100的随机数,并放到一个数组中,把数组中大于等于10的数字放到一个list集合中,并打印到控制台。
public class Test {
public static void main(String[] args){
Random random = new Random(); // 随机数
int[] arr = new int[10]; // 十个数的数组
for (int i = 0; i < 10; i++) { // 数组中放入随机数
arr[i] = random.nextInt(100) + 1; // 要求1-100的随机数,所以要 +1
}
List list = new ArrayList(); // 创建一个集合
for (int i = 0; i < arr.length; i++) { // 循环数组,判断数组元素是否大于10
if (arr[i] >= 10){ //如果大于十,放入集合中
list.add(arr[i]);
}
}
System.out.println(Arrays.toString(arr)); // 打印数组
System.out.println(list); // 打印集合
/* 结果 :
[8, 53, 10, 20, 72, 95, 70, 80, 2, 29]
[53, 10, 20, 72, 95, 70, 80, 29]
*/
}
}
题目10
已知数组存放一批QQ号码,QQ号码最长为11位,最短为5位String[] strs = {“12345”,“67891”,“12347809933”,“98765432102”,“67891”,“12347809933”}。 将该数组里面的所有qq号都存放在LinkedList中,将list中重复元素删除,将list中所有元素分别用迭代器和增强for循环打印出来。
public class Test {
public static void main(String[] args){
String[] strs = {"12345","67891","12347809933","98765432102","67891","12347809933"}; // 已知qq号
List list = new LinkedList(); // 创建集合
for (int i = 0; i < strs.length; i++) {// 循环strs数组的元素
list.add(strs[i]); // 把数组的元素遍历到集合中
}
// 判断元素是否重复,双循环,外循环控制元素和后面的元素依次对比,内循环取出元素,如果元素相同,则删除
int a = list.size(); // 设置a为list集合的长度
for (int i = 0; i < a; i++) {
String str = (String) list.get(i); // 设置一个数,跟后面的数进行对比
for (int j = i + 1; j < a; j++) {
String str2 = (String) list.get(j);
if (str.equals(str2)){ // 如果两个数相同,则删除后面的数
list.remove(j);
a--; // 同时,数组长度-1
}
}
}
System.out.println(list);
}
}
or
public class QQNumberExample {
public static void main(String[] args) {
String[] strs = {"12345", "67891", "12347809933", "98765432102", "67891", "12347809933"};
// 将QQ号存放在LinkedList中
LinkedList<String> qqList = new LinkedList<>();
for (String qq : strs) {
if (qq.length() >= 5 && qq.length() <= 11) {
qqList.add(qq);
}
}
// 使用HashSet去重
HashSet<String> qqSet = new HashSet<>(qqList);
qqList.clear();
qqList.addAll(qqSet);
// 用迭代器打印
System.out.println("使用迭代器打印:");
Iterator<String> iterator = qqList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 用增强for循环打印
System.out.println("\n使用增强for循环打印:");
for (String qq : qqList) {
System.out.println(qq);
}
}
}
题目11
分别用Comparable和Comparator两个接口对下列四位同学的成绩做降序排序,如果成绩一样,那在成绩排序的基础上按照年龄由小到大排序。
姓名(String)年龄(int)分数(float)
liusan 20 90.0F
lisi 22 90.0F
wangwu 20 99.0F
sunliu 22 100.0F
编写一个Student类用来实现Comparable接口,并在其中重写CompareTo(Student o)方法
在主函数中使用Comparable 与 Comparetor分别对ArrayList进行排序。
首先,你需要创建一个
Student
类并实现Comparable<Student>
接口,然后在主函数中使用Comparable
和Comparator
对ArrayList
进行排序。以下是示例代码:@Data @NoArgsConstructor @AllArgsConstructor class Student implements Comparable<Student> { private String name; private int age; private float score; // 实现 Comparable 接口的 compareTo 方法 @Override public int compareTo(Student o) { // 先按分数降序排序 int scoreCompare = Float.compare(o.score, this.score); if (scoreCompare != 0) { return scoreCompare; } // 如果分数相同,则按年龄升序排序 return Integer.compare(this.age, o.age); } } public class Main{ public static void main(String[] args) { ArrayList<Student> students = new ArrayList<>(); students.add(new Student("liusan", 20, 90.0F)); students.add(new Student("lisi", 22, 90.0F)); students.add(new Student("wangwu", 20, 99.0F)); students.add(new Student("sunliu", 22, 100.0F)); // 使用 Comparable 排序 System.out.println("使用 Comparable 排序:"); Collections.sort(students); for (Student student : students) { System.out.println(student); } // 使用 Comparator 排序 System.out.println("\n使用 Comparator 排序:"); Comparator<Student> comparator = Comparator .comparing(Student::getScore) .thenComparing(Student::getAge); Collections.sort(students, comparator.reversed()); for (Student student : students) { System.out.println(student); } } }
在这个例子中,
Student
类实现了Comparable<Student>
接口,重写了compareTo
方法。然后在主函数中使用Collections.sort
方法分别使用Comparable
和Comparator
进行排序。在使用Comparator
排序时,使用了Comparator.reversed()
来进行降序排序。
题目12
现在有一个map集合如下:
Map<Integer,String> map = new HashMap<Integer, String>();
map.put(1, “张三丰”);
map.put(2, “周芷若”);
map.put(3, “汪峰”);
map.put(4, “灭绝师太”);
要求:
1.遍历集合,并将序号与对应人名打印。
2.向该map集合中插入一个编码为5姓名为郭靖的信息
3.移除该map中的编号为1的信息
4.将map集合中编号为2的姓名信息修改为"周林"
public class Test {
public static void main(String[] args){
Map<Integer,String> map = new HashMap<Integer, String>();
map.put(1, "张三丰");
map.put(2, "周芷若");
map.put(3, "汪峰");
map.put(4, "灭绝师太");
// 遍历集合
// 1. 转换成set格式
Set<Object> set = Collections.singleton(map.keySet());
Set<Object> set1 = Collections.singleton(map.values());
for (Object o : set){
System.out.println(o);
}
for (Object o : set1){
System.out.println(o);
}
// 2.forEach
map.forEach((key,vaule) ->{ System.out.println(key + " : " + vaule); });
// 向该map集合中插入一个编码为5姓名为郭靖的信息
map.put(5, "郭靖");
System.out.println("添加 : " + map);
// 移除该map中的编号为1的信息
System.out.println("删除 : " + map.remove(1));
// 将map集合中编号为2 的姓名修改为"周林"
System.out.println(map.replace(2, "周林"));
System.out.println(map);
}
}
题目13
有2个数组,第一个数组内容为:[黑龙江省,浙江省,江西省,广东省,福建省], 第二个数组为:[哈尔滨,杭州,南昌,广州,福州], 将第一个数组元素作为key,第二个数组元素作为value存储到Map集合中。 如{黑龙江省=哈尔滨, 浙江省=杭州, …}
public class demo5 {
public static void main(String[] args){
String[] str1 ={"黑龙江省","浙江省","江西省","广东省","福建省",};
String[] str2 ={"哈尔滨","杭州","南昌","广州","福州",};
Map<String ,String> map = new HashMap<>();
for (int i = 0; i < str1.length; i++) {
map.put(str1[i],str2[i] );
}
map.forEach((key,value) -> {
System.out.println(key + " : " + value);
});
}
}
题目14
定义一个泛型为String类型的List集合,统计该集合中每个字符 (注意,不是字符串)出现的次数。例如:集合中有”abc”、”bcd”两个元素, 程序最终输出结果为:“a = 1,b = 2,c = 2,d = 1”。
public class Test {
public static void main(String[] args){
List<String> list = new ArrayList<>();
list.add("aaabc");
list.add("bcddd");
// 建立一个泛型为char的数组
List<Character> charList = new ArrayList<>();
// 需要先遍历集合,取出所有的元素
for (String s : list){
for (int i = 0; i < s.length(); i++) { // 遍历字符串并取出
charList.add(s.charAt(i)); // 向集合里放入取出的字符
}
}
// 查看charList集合中的元素,有多少重复的
int a = charList.size(); // 遍历的长度为charList集合的长度
for (int i = 0; i < a - 1; i++) {
int num = 1; // 设置一个数接收每个元素有几个,默认有一个
for (int j = i + 1; j < a; j++) { // 循环判断元素后面是否有和当前元素相同的元素
if (charList.get(i).equals(charList.get(j))){ // 判断是否相同,如果相同
charList.remove(j); // 删除该元素
num++; // 记录这个元素共出现几次
a--; // 总长度减一
j--; // 因为删除了一个元素,所以 j+1 位置的元素到j位置上了,要把 j-1
}
}
// System.out.println(charList); // 打印集合
System.out.println(charList.get(i) + " : " + num); // 打印集合元素出现了几次
}
}
}
题目15
设计Account 类如下:
private long id;
private double balance;
private String password; 要求完善设计,使得该Account 对象能够自动分配自增id。给定一个List 如下:
List list = new ArrayList();
list.add(new Account(10.00, “1234”));
list.add(new Account(15.00, “5678”));
list.add(new Account(0, “1010”)); 要求把List 中的内容放到一个Map 中,该Map 的键为id,值为相应的Account 对象。 最后遍历这个Map,打印所有Account 对象的id 和余额。
public class Test {
public static void main(String[] args){
List<Account> list = new ArrayList();
list.add(new Account(10.00,"1234")); // new ==> Account
list.add(new Account(15.00,"5678"));
list.add(new Account(0,"1010"));
Map<Integer,Account> map = new HashMap<>(); // 创建Map集合
for(Account o : list){
// System.out.println(o.getId()); // 取出遍历数组的id
map.put(o.getId(), o); // 将map集合的Key为id,Value为Account对象
}
// System.out.println(map); // 输出map集合
Set<Integer> set = map.keySet();
for (Integer a : set){
System.out.println("id : "+ a + "余额 : " + map.get(a).getPasswork()); // id 和 余额
}
}
}
public class Account {
private static int num = 1;
private int id;
private double balance;
private String passwork;
public Account(double balance, String passwork) {
this.id = num++; // id自增
this.balance = balance;
this.passwork = passwork;
// id++;
}
public static int getNum() {
return num;
}
public static void setNum(int num) {
Account.num = num;
}
public Account() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPasswork() {
return passwork;
}
public void setPasswork(String passwork) {
this.passwork = passwork;
}
@Override
public String toString() {
return "Account{" +
"balance=" + balance +
", passwork='" + passwork + '\'' +
'}';
}
}
题目16
创建好员工基类和程序员、项目经理子类的基础上,创建一个测试类。 创建一个ArrayList集合对象,要求保存两个程序员和两个项目经理的对象, 并循环调用show的方法显示详细信息。
public class Test {
public static void main(String[] args){
List<Staff> collation = new ArrayList<>(); // 泛型 ==> 基类
collation.add(new Programmer());
collation.add(new PM());
collation.add(new Programmer());
collation.add(new PM());
System.out.println(collation.size()); // 输出collation集合存储元素的个数
for (Staff s : collation) { // 遍历collection
s.post();
}
}
}
/*
员工基类,定义为抽象类,抽象方法
*/
public abstract class Staff {
public abstract void post();
}
/*
程序员类
*/
public class Programmer extends Staff {
@Override
public void post() {
System.out.println("我是程序员~");
}
}
/*
项目经理类
*/
public class PM extends Staff {
@Override
public void post() {
System.out.println("我是项目经理~");
}
}
题目17
创建Student类,属性包括id[1-40],scroe[0-100], 所有属性随机生成。创建Set集合,保存20个对象,找到分数最高与最低的学生。
public class Test {
public static void main(String[] args){
TreeSet<Student> treeSet = new TreeSet<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
int a = random.nextInt(40) + 1;
int b = random.nextInt(101);
treeSet.add(new Student(a, b));
}
System.out.println("学号\t成绩");
for(Student s : treeSet){
System.out.println(s.getId() + "\t\t" +
s.getScore());
}
System.out.println("最高分 : " + treeSet.first().getScore());
System.out.println("最低分 : " + treeSet.last().getScore());
}
}
public class Student implements Comparable<Student> {
private int id;
private int score;
public Student(int id, int score) {
this.id = id;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public int compareTo(Student o) {
if (this.getScore() == o.getScore()){
return this.getId() - o.getId();
}else{
return o.getScore() - this.getScore();
}
}
@Override
public String toString() {
return id + "\t" + score + "\n";
}
}
(第二种方法) 创建Student类,属性包括id[1-40],scroe[0-100], 所有属性随机生成。创建Set集合,保存20个对象,找到分数最高与最低的学生。
public class Test {
public static void main(String[] args) {
// mapTest();
// work();
// TODO 最高分最低分排名未完成
}
public static void work(){
LinkedHashSet<Student> set = new LinkedHashSet<>();
for (int i = 0; i < 20; i++) {
set.add(new Student(Student.getId(),Student.getScroe()));
}
int max = 0;
int min = 100;
System.out.println("学号 成绩");
for(Student s : set){
System.out.println(s);
}
}
public static void mapTest(){
HashSet<Student> set = new HashSet<>(); // 创建一个set集合,同时set集合的泛型是Student
Map<Integer,Integer> map = new HashMap<>();
while(map.size() < 20){
map.put(Student.getId(), Student.getScroe());
}
set.toArray();
System.out.println("学号 成绩");
Set<Map.Entry<Integer,Integer>> set2 = map.entrySet();
for (Map.Entry<Integer,Integer> s : set2){
System.out.println(s.getKey() + "\t" + s.getValue());
}
}
}
public class Student{
private int id;
private int scroe;
Random random = new Random();
public Student(int i, int id) {
this.id = (random.nextInt(39) + 1);
this.scroe = random.nextInt(101);
}
public static int getId() {
Random random = new Random();
return (random.nextInt(39) + 1);
}
public void setId(int id) {
this.id = id;
}
public static int getScroe() {
Random random = new Random();
return random.nextInt(101);
}
public void setScroe(int scroe) {
this.scroe = scroe;
}
@Override
public String toString() {
return id + "\t " + scroe;
}
}
题目18
已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚,日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利。
public class Test {
public static void main(String[] args){
// 两种方式
no1();
no2();
}
public static void no2(){
Random random = new Random();
List list = new ArrayList();
// 把每一个国家的长度都保持一致,避免打印的时候出现错位的情况
list.add("科特迪瓦");list.add("阿根廷 ");list.add("澳大利亚");list.add("塞尔维亚");list.add("荷兰 ");list.add("尼日利亚");list.add("日本 ");list.add("美国 ");
list.add("中国 ");list.add("新西兰 ");list.add("巴西 ");list.add("比利时 ");list.add("韩国 ");list.add("喀麦隆 ");list.add("洪都拉斯");list.add("意大利 ");
int a = list.size(); // 设置循环次数是集合的长度
for (int i = 0; i < 4; i++) { // 设置双循环,外循环是第几组
System.out.print("第" + i + "组 : ");
for (int j = 0; j < 4; j++) { // 内循环是对应的四个组
System.out.print(list.get(random.nextInt(a)) + "\t"); //
a--; // 随机一次之后随机数删除1,不能重复出现两个组
}
System.out.println();
}
}
public static void no1(){
Random random = new Random();
List list = new ArrayList();
// 把每一个国家的长度都保持一致,避免打印的时候出现错位的情况
list.add("科特迪瓦");list.add("阿根廷 ");list.add("澳大利亚");list.add("塞尔维亚");list.add("荷兰 ");list.add("尼日利亚");list.add("日本 ");list.add("美国 ");
list.add("中国 ");list.add("新西兰 ");list.add("巴西 ");list.add("比利时 ");list.add("韩国 ");list.add("喀麦隆 ");list.add("洪都拉斯");list.add("意大利 ");
List arr = new ArrayList(); // 设置一个新数组,接收随机数
for (int i = 0; i < 16; i++) {
boolean flag = true;
while(flag) { // 循环,如果随机数已经存在了就继续随机
int a = random.nextInt(16);
if (arr.indexOf(a) == -1){ // 判断随机数a是否存在于arr集合中,存在返回索引,不存在返回-1
arr.add(a);
flag = false;
}
}
}
System.out.println("第一组\t\t第二组\t\t第三组\t\t第四组");
for (int i = 1; i <= arr.size(); i++) { // 设置循环十六次,因为每四次换行,i%4==0 当i=0时直接换行,所以i从1开始
int a = (int) arr.get(i-1); // 取出随机出来的数 i从1开始,所以要减一
System.out.print(list.get(a) + "\t");
if (i % 4 == 0 ){ // 每四个国家循环完就换行
System.out.println();
}
}
}
}