集合1
集合
Collection:
- List: 元素有序且允许发生重复,有索引
- ArrayList: 底层数据结构是数组,查询快,增删慢
- Vector
- LinkedList
- Set:
例子:
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add("hello");
list1.add("world");
list1.add("hello");
list1.add("java");
list1.add("flink");
Iterator iterator = list1.iterator();
while (iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
}
}
链表:
Collection:
- List: 元素有序且允许发生重复,有索引
- ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高
- Vector: 底层数据结构是数组,查询快,增删慢,线程安全的,效率低,即便是这样,我们以后也不用
- LinkedList: 底层数据结构是双链表,增删快,查询慢,线程不安全,效率高
- Set:
LinkedList:特有的功能
LinkedList类特有功能【由于底层是链表】
public void addFirst(Object e)及addLast(Object e)
public Object getFirst()及getLast()
public Object removeFirst()及public Object removeLast()
例子:
public class LinkedListDemo1 {
public static void main(String[] args) {
//LinkedList() 构造一个空列表。
LinkedList list1 = new LinkedList();
list1.add("hello");
list1.add("world");
list1.add("hello");
list1.add("clickhouse");
list1.add("redis");
System.out.println("list1: "+list1);
// Iterator iterator = list1.iterator();
// while (iterator.hasNext()){
// System.out.println(iterator.next());
// }
System.out.println("-----------------------------------------");
//public void addFirst(Object e)及addLast(Object e) 在头部添加一个元素或者尾部添加元素
list1.addFirst("kafka");
list1.addLast("cdh");
System.out.println("list1: "+list1);
//public Object getFirst()及getLast()
System.out.println(list1.getFirst());
System.out.println(list1.getLast());
System.out.println("list1: "+list1);
//public Object removeFirst()及public Object removeLast() 从集合中移除第一个元素或最后一个元素
System.out.println(list1.removeFirst());
System.out.println(list1.removeLast());
System.out.println("list1: "+list1);
}
}
练习:
去除集合中字符串的重复值(字符串的内容相同)
去除集合中字符串的重复值(字符串的内容相同)
public class ArrayListTest1 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add("hello");
list1.add("world");
list1.add("hello");
list1.add("java");
list1.add("flink");
list1.add("hello");
list1.add("java");
list1.add("world");
list1.add("hello");
System.out.println("list1: "+list1);
System.out.println("----------------------------");
//创建一个新的集合,遍历旧集合
//如果新集合中有该元素,说明重复,不添加
//反之添加到新集合中,最后新集合中存储去重后的结果
ArrayList list2 = new ArrayList();
Iterator iterator = list1.iterator();
while (iterator.hasNext()){
String s = (String) iterator.next();
if(!list2.contains(s)){
list2.add(s);
}
}
System.out.println("list2: "+list2);
}
}
去除集合中自定义对象的重复值(对象的成员变量值都相同)
去除集合中自定义对象的重复值(对象的成员变量值都相同)
public class ArrayListTest2 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
Student s1 = new Student("张成阳", 18);
Student s2 = new Student("方直", 19);
Student s3 = new Student("张成阳", 18);
Student s4 = new Student("方直", 19);
Student s5 = new Student("张成阳", 18);
Student s6 = new Student("方直", 19);
list1.add(s1);
list1.add(s2);
list1.add(s3);
list1.add(s4);
list1.add(s5);
list1.add(s6);
System.out.println("list1: "+list1);
System.out.println("----------------------------");
//创建一个新的集合,遍历旧集合
//如果新集合中有该元素,说明重复,不添加
//反之添加到新集合中,最后新集合中存储去重后的结果
ArrayList list2 = new ArrayList();
Iterator iterator = list1.iterator();
while (iterator.hasNext()){
Student s = (Student) iterator.next();
if(!list2.contains(s)){
list2.add(s);
}
}
/*
我们按照去重字符串的逻辑对学生对象进行去重,发现不太行
旧集合中的每一个学生对象都添加到了新集合中‘
从结果来看。每一个学生对象41行的判断【!list2.contains(s)】都是true
list2.contains(s) 一直都是false
要想知道为什么list2.contains(s)一直都是false的话,就应该去看contains的源码
public boolean contains(Object o) {
// o - new Student("张成阳", 18);
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
// o - new Student("张成阳", 18);
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < this.size; i++) // 遍历新集合,调用元素的equals方法挨个与新集合中的元素进行比较
if (o.equals(elementData[i]))
return i; // i的值一定是大于等于0
}
return -1;
}
从源码上来看,底层是调用了元素类型中的equals方法,而我们的元素是学生类,学生类中没有重写该方法,用的是父类Object类中的
equals方法,比较的是地址值,而每一学生都是new出来的,地址肯定不一样。
解决方案:元素类型中重写equals方法即可
*/
System.out.println("list2: "+list2);
}
}
请用LinkedList模拟栈数据结构的集合,并测试。栈的特点:先进后出
请用LinkedList模拟栈数据结构的集合,并测试
栈的特点:先进后出
题目的意思是:自己造一个类,底层封装LinkedList,自己定义方法
创建自己的类对象,调用自己定义的方法,来实现栈。
解:
import java.util.LinkedList;
public class MyStack {
private LinkedList list;
public MyStack(){
list = new LinkedList();
}
public void shuJiaAddElement(Object o){
list.addFirst(o);
}
public Object shuJiaGetElement(){
return list.removeFirst();
}
public int getSize(){
return list.size();
}
@Override
public String toString() {
return "MyStack{" +
"list=" + list +
'}';
}
}
public class LinkedListTest1 {
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.shuJiaAddElement("hello");
myStack.shuJiaAddElement("world");
myStack.shuJiaAddElement("java");
myStack.shuJiaAddElement("hello");
myStack.shuJiaAddElement("hadoop");
System.out.println("myStack: " + myStack);
int size = myStack.getSize();
for (int i = 0; i < size; i++) {
System.out.println(myStack.shuJiaGetElement());
}
}
}
泛型
回忆下,在此之前,我们的集合可以存放任意类型的元素,但是实际开发的时候,一个集合规定只允许放一种数据类型的元素
java中的集合提供了一种类似于数组定义时确定元素类型的方式,泛型
泛型:
语句定义格式:<引用数据类型>
将引用数据类型当作参数一样传递
泛型的好处:
泛型的好处:
1、减少了程序中的黄色警告
2、遍历的时候不需要再做向下转型了,因为在创建集合对象的时候,给定了泛型的类型
public class FanXingDemo1 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>(); // 泛型定义了集合中的元素数据类型,右边的尖括号泛型可以不写,自动类型推断
// ArrayList list1 = new ArrayList();
// list1.add()
// list1.add(10);
list1.add("hello");
list1.add("world");
list1.add("java");
list1.add("hadoop");
list1.add("world");
list1.add("hello");
list1.add("flink");
// list1.add(false);
System.out.println("list1: "+list1);
System.out.println("----------------------------");
Iterator<String> iterator = list1.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s+"-"+s.length());
}
}
}
泛型将来遇到的场景
泛型类:将泛型定义在类上
<>里面的参数是为了将来调用时接收传入的引用数据类型,相当于一个形参一样,符合变量标识符命名规则就可以了
但是规范来说,泛型的名字,由一个大写的英文字母表示
class Demo1<A>{
public void fun1(A a){
System.out.println(a);
}
}
public class FanXingDemo2 {
public static void main(String[] args) {
Demo1<Integer> stringDemo1 = new Demo1<>();
stringDemo1.fun1(100);
// stringDemo1.fun1("hello");
Demo1<String> d2 = new Demo1<>();
d2.fun1("hello");
// d2.fun1(100);
}
}
把泛型定义在方法上 格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
class Demo2<Q>{
public <E> void fun1(E e){
System.out.println(e);
}
public void fun2(Q q){
System.out.println(q);
}
}
public class FanXingDemo3 {
public static void main(String[] args) {
Demo2<Double> demo2 = new Demo2<>();
demo2.fun1("hello");
demo2.fun1(100);
demo2.fun2(12.34);
}
}
泛型接口
把泛型定义在接口上,格式:public interface 接口名<泛型类型1…>
interface Inter<W>{
void fun1(W w);
}
class InterImpl<W> implements Inter<W>{
@Override
public void fun1(W w) {
System.out.println(w);
}
}
public class FanXingDemo4 {
public static void main(String[] args) {
}
}
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向下限定,E及其子类
? super E
向上限定,E及其父类
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
class Demo3 {
public void fun1(Collection<?> c1) { // 可以接收元素是任意引用数据类型的Collection集合对象
System.out.println("c1: " + c1);
}
public void fun2(Collection<? extends Animal> c1) { // 可以接收元素是Animal类型或Animal的子类类型的的Collection集合对象
System.out.println("c1: " + c1);
}
public void fun3(Collection<? super Animal> c1) { // 可以接收元素是Animal类型或Animal的父类类型的的Collection集合对象
System.out.println("c1: " + c1);
}
// public void fun1(Xxxx<?> c1) { // 可以接收元素是任意引用数据类型的Xxxx对象
// System.out.println("c1: " + c1);
// }
}
public class FanXingDemo5 {
public static void main(String[] args) {
Demo3 d1 = new Demo3();
ArrayList<Animal> list1 = new ArrayList<>();
ArrayList<Dog> list2 = new ArrayList<>();
ArrayList<Cat> list3 = new ArrayList<>();
ArrayList<Object> list4 = new ArrayList<>();
//Collection<?> c1
d1.fun1(list1);
d1.fun1(list2);
d1.fun1(list3);
d1.fun1(list4);
d1.fun2(list1);
d1.fun2(list2);
d1.fun2(list3);
// d1.fun2(list4);
d1.fun3(list1);
// d1.fun3(list2);
// d1.fun3(list3);
d1.fun3(list4);
//public boolean addAll(Collection<? extends Animal> c)
ArrayList<Animal> animals = new ArrayList<>();
animals.addAll(list1);
animals.addAll(list2);
animals.addAll(list3);
// animals.addAll(list4);
}
}
一些小知识点
增强for循环:
是用来代替迭代器的,可以遍历数组和Collection集合
语句定义格式:
for(元素的数据类型 变量名 : 数组或Collection集合){
使用变量名;
}
例子
public class ZengForDemo {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("hello");
list1.add("world");
list1.add("java");
list1.add("hadoop");
list1.add("world");
list1.add("hello");
list1.add("flink");
System.out.println("list1: "+list1);
System.out.println("----------------------------");
for (String s : list1) {
System.out.println(s + "-" + s.length());
}
//
// for (String s : list1) {
// System.out.println(s + "-" + s.length());
// }
System.out.println("----------------------------");
int[] arr = {11,22,33,44,55};
for(int i : arr){
System.out.println(i);
}
}
}
导入方法例:max
package shujia.day10;
//import static java.lang.Math.max;
//import static java.lang.Math.min;
import static java.lang.Math.*;
public class StaticImportDemo {
public static void main(String[] args) {
// System.out.println(Math.max(12,34));
// System.out.println(Math.max(23,1));
// System.out.println(Math.max(42,51));
// System.out.println(Math.max(12,124));
System.out.println(max(123, 5));
// System.out.println(min(213, 6));
System.out.println(Math.max(123,5));
}
public static int max(int a, int b) {
return a + b;
}
}
可变参数:
语句定义格式:数据类型... arr
注意事项
注意事项:
1、方法定义时,如果有可变参数,可变参数必须在最后一个定义
2、一个方法定义时,只能有一种类型是可变参数
例子:
public class KeBianCanDemo1 {
public static void main(String[] args) {
// //需求:求两个int数之和
// int a = 3;
// int b = 4;
// sum(a, b);
//
// //需求:求三个int数之和
// int c = 5;
// sum(a, b, c);
// //需求:求n个int数之和
// int d = 6;
// sum(a,b,c,d);
//调用方法,传入一个学生的姓名和若干门成绩
stuScore("zcy",89,98);
stuScore("fz",99,78,91);
//可变参数使用的例子
List<String> list = Arrays.asList("hello", "world", "hello", "java", "hadoop");
}
public static void stuScore(String name, int... scores){
int sum = 0;
for (int i : scores) {
sum+=i;
}
System.out.println("姓名:"+name+"总成绩:"+sum);
}
public static void sum(int... arr) { // 可以传入若干个int类型的值,被封装到了一个数组中,数组的名字叫做arr
// System.out.println(a + b);
int sum = 0;
for (int i : arr) {
sum+=i;
}
System.out.println(sum);
}
// public static void sum(int a, int b, int c) {
// System.out.println(a + b + c);
// }
//
// public static void sum(int a, int b) {
// System.out.println(a + b);
// }
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现