首页 > 其他分享 >2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层

时间:2023-06-29 20:31:40浏览次数:53  
标签:index return LinkedList Iterator int elementData new public 底层

1. 机试题

1、输入一个字符串,判断判断这个字符串是否对称

例如abcba算对称 abccba也算对称

package com.wz.test01;

import java.util.Scanner;

public class test01 {
    /**
     * 输入一个字符串,判断判断这个字符串是否对称
     * 例如abcba算对称  abccba也算对称
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入字符串:");
        String str = sc.next();
        //定义两个指针
        int start=0;
        int end=str.length()-1;
        boolean flag=true;
        while(start<end){
            char c1 = str.charAt(start);
            char c2 = str.charAt(end);
            if (c1!=c2){
                flag=false;
                break;
            }
            start++;
            end--;
        }
        if (flag){
            System.out.println("此字符串对称!");
        }else {
            System.out.println("此字符串不对称!");
        }
        sc.close();
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_ListIterator

2、实现HashMap的value排序

  1. 创建HashMap集合
  2. 利用EntrySet获取到集合内元素
  3. 把entrySet转为ArrayList数组
  4. 利用数组中的sort方法进行排序
  5. 重写compare排序规则
package com.wz.test02;

import java.util.*;

public class test01 {
    /**
     * 实现HashMap的value排序
     */
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("张三",26);
        map.put("李四",22);
        map.put("王五",16);
        map.put("赵六",25);
        map.put("AAA",21);
        map.put("BBB",19);
        map.put("CCC",28);
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        ArrayList<Map.Entry<String, Integer>> list = new ArrayList<>(entrySet);
        list.sort(new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return Integer.compare(o1.getValue(),o2.getValue());
            }
        });
        for (Map.Entry<String,Integer> entry:list
             ) {
            System.out.println(entry);
        }
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_ListIterator_02

3、设计一个线程(使用自定义线程池),使得字符串”成都是一座你来了就不想走的城市” 每隔1秒钟输出一个字符。 运 行结果如下:(多行输出)

成 成都 成都是 成都是一 成都是一座 成都是一座你 …… 成都是一座你来了就不想走的城市

package com.wz.test03;

public class Task implements Runnable{
    @Override
    public void run() {

        String str = "成都是一座你来了就不想走的城市";
        //字符串转换为字符数组
        char[] cs = str.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            for (int j = 0; j <= i; j++) {
                System.out.print(cs[j]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
            System.out.println();
        }
    }
}
package com.wz.test03;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class test01 {
    /**
     * 设计一个线程(使用自定义线程池),使得字符串”成都是一座你来了就不想走的城市” 每隔1秒钟输出一个字符。
     * 运行结果如下:(多行输出)
     * 成
     * 成都
     * 成都是
     * 成都是一
     * 成都是一座
     * 成都是一座你
     * 	……
     * 成都是一座你来了就不想走的城市
     */
    public static void main(String[] args) {
        /**
         * 自定义线程池
         * 1,核心线程数
         * 1,最大线程数
         * 0,闲置时间
         * TimeUnit.SECONDS,时间单位
         * new ArrayBlockingQueue<>(1)任务队列
         */
        ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1));
        //创建任务对象
        Task task = new Task();
        //提交任务
        pool.submit(task);
        //关闭线程池
        pool.shutdown();
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_Iterator_03

4、任意输入一个字符串,编程输出这个字符串中第一个没有重复的字符的下标和该字符。如字符串为“dfablkfdalk”,则输出:3-b,如果所有字符均重复则输出“没有不重复的字符”。

package com.wz.test04;

import java.util.Scanner;

public class test01 {
    /**
     * 任意输入一个字符串,编程输出这个字符串中第一个没有重复的字符的下标和该字符。
     * 如字符串为“dfablkfdalk”,则输出:3-b,如果所有字符均重复则输出“没有不重复的字符”。
     */
    public static void main(String[] args) {
        System.out.println("请输入一个字符串:");
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        char[] cs = str.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            char c = cs[i];
            boolean flag=true;
            for (int j = i+1; j < cs.length; j++) {
                if (c==cs[j]){
                    flag = false;
                    break;
                }
            }
            if (flag){
                System.out.println(i+"--"+c);
                break;
            }
        }
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_迭代器底层_04

5、我们班现在要选举产生最卷的学生,每人有一次投票权,每人的票可以投给任意的学生,用面向对象编程实现这个功能。(假设班级人数6人)

package com.wz.test05;

public class Student {
    private String name;
    private int count;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", count=" + count +
                '}';
    }
}
package com.wz.test05;

import java.awt.*;
import java.util.ArrayList;
import java.util.Scanner;


public class test01 {
    /**
     * 我们班现在要选举产生最卷的学生,每人有一次投票权,每人的票可以投给任意的学生
     * 用面向对象编程实现这个功能。(假设班级人数6人)
     */
    public static void main(String[] args) {

        java.util.ArrayList<Student> list = new ArrayList<>();

        list.add(new Student("张三"));
        list.add(new Student("李四"));
        list.add(new Student("王五"));
        list.add(new Student("赵六"));
        list.add(new Student("AAA"));
        list.add(new Student("BBB"));

        Scanner scan = new Scanner(System.in);

        for (int i = 0; i < list.size(); i++) {
            Student student = list.get(i);
            System.out.println("请" + student.getName() + "同学投票:");
            for (int j = 0; j < list.size(); j++) {
                System.out.println((j+1) + " -- " + list.get(j).getName());
            }
            int index = scan.nextInt()-1;
            list.get(index).setCount(list.get(index).getCount()+1);
        }

        for (Student student : list) {
            System.out.println(student);
        }

        scan.close();
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_LinkedList底层_05

6、郭靖去银行办了一张银行卡和存折,卡上存了1000元,郭靖把存折给了黄蓉,他们俩同时去银行两个柜台,一人用银行卡,一人用存折取款,每次只能取100块,请使用多线程编程实现他们取出这1000块钱的过程。

package com.wz.test06;

public class Task  implements Runnable{
    private int money = 1000;
    @Override
    public void run() {
        while (money>=100){
            synchronized (this){
                if (money>=100){
                    money-=100;
                    System.out.println(Thread.currentThread().getName()+"取钱了,余额为:"+money);
                }

            }
        }
    }
}
package com.wz.test06;

public class test01 {
    /**
     * 郭靖去银行办了一张银行卡和存折,卡上存了1000元,郭靖把存折给了黄蓉,
     * 他们俩同时去银行两个柜台,一人用银行卡,一人用存折取款,
     * 每次只能取100块,请使用多线程编程实现他们取出这1000块钱的过程。
     */
    public static void main(String[] args) {
        Task task = new Task();
        Thread t1 = new Thread(task,"郭靖");
        Thread t2 = new Thread(task, "黄蓉");
        t1.start();
        t2.start();
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_Iterator_06

7、编写服务器和客户端,实现在服务器不断往客户端发送一个用户对象的过程,要求:服务器不断发送用户对象,客户端收到对象后不断存储在本地文件中。

注意:使用完需要关闭资源

package com.wz.test07;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client {
    /**
     * 编写服务器和客户端,实现在服务器不断往客户端发送一个用户对象的过程,
     * 要求:服务器不断发送用户对象,客户端收到对象后不断存储在本地文件中。
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        Socket socket = new Socket("127.0.0.1", 8080);

        InputStream in = socket.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(in);
        Student stu = null;
        while((stu = (Student) ois.readObject()) != null){
            System.out.println(stu);
        }

    }
}
package com.wz.test07;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    /**
     * 编写服务器和客户端,实现在服务器不断往客户端发送一个用户对象的过程,
     * 要求:服务器不断发送用户对象,客户端收到对象后不断存储在本地文件中。
     */
    public static void main(String[] args) throws Exception {


        ServerSocket server = new ServerSocket(8080);
        Socket socket = server.accept();

        Scanner scanner = new Scanner(System.in);

        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        while (true) {
            System.out.println("name:");
            oos.writeObject(new Student(scanner.next()));
        }



    }
}
package com.wz.test07;


import java.io.Serializable;

public class Student implements Serializable{

    private static final long serialVersionUID = -3055854463625244431L;
    private String name;
    private int count;//获得的票数

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", count=" + count + "]";
    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_迭代器_07

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_迭代器_08

8、完成下列需求

1)创建部门枚举,对象有:JAVA、HTML、PYTHON 2)创建员工实体类,属性有:姓名、年龄、薪资、部门枚举 3) 实现员工的管理系统(底层数据结构不限),有添加员工、删除员工、修改员工、查询员工 4)根据姓名、年龄段、薪资、部门等各种情况查询学生 5)编写统计员工信息方法,统计最高工资的员工、最低薪资的员工、根据部门统计员工,通过Stream流统计

//部门枚举
package com.wz.test08;

public enum Course {
    JAVA,HTML,PYTHON;
}
package com.wz.test08;

public class Staff {
    private String name;
    private int age;
    private double salary;
    private Course course;

    public Staff() {
    }

    public Staff(String name, int age, double salary, Course course) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.course = course;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "Staff{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", course=" + course +
                '}';
    }
}
package com.wz.test08;

import java.util.*;
import java.util.stream.Collectors;

public class test01 {
    /**
     * 1)创建部门枚举,对象有:JAVA、HTML、PYTHON
     * 2)创建员工实体类,属性有:姓名、年龄、薪资、部门枚举
     * 3) 实现员工的管理系统(底层数据结构不限),有添加员工、删除员工、修改员工、查询员工
     * 4)根据姓名、年龄段、薪资、部门等各种情况查询学生
     * 5)编写统计员工信息方法,统计最高工资的员工、最低薪资的员工、根据部门统计员工,通过Stream流统计
     */
    public static void main(String[] args) {
        ArrayList<Staff> list = new ArrayList<>();

        list.add(new Staff("张三",23,9500,Course.JAVA));
        list.add(new Staff("李四",20,10000,Course.JAVA));
        list.add(new Staff("王五",21,8500,Course.JAVA));
        list.add(new Staff("赵六",18,9000,Course.PYTHON));
        list.add(new Staff("AAA",19,5500,Course.HTML));
        list.add(new Staff("BBB",27,6500,Course.PYTHON));
        list.add(new Staff("CCC",30,7500,Course.JAVA));
        list.add(new Staff("DDD",29,15000,Course.HTML));
        list.add(new Staff("EEE",24,12000,Course.PYTHON));
        //根据下标删除
        list.remove(3);
        //根据下标修改元素
        list.get(1).setAge(18);

        for (Staff staff:list
             ) {
            System.out.println(staff);
        }
        System.out.println("-------------------");
        ArrayList<Staff> newList = new ArrayList<>();
        for (Staff staff:list
             ) {
            if (staff.getCourse()==Course.JAVA){
                newList.add(staff);
            }
        }
        for (Staff staff:newList
             ) {
            System.out.println(staff);
        }

        System.out.println("--------------------");

        //编写统计员工信息方法,统计最高工资的员工、最低薪资的员工、根据部门统计员工,通过Stream流统计
        //统计最高工资的员工
        list.stream().sorted((staff1,staff2)->{
            return Double.compare(staff2.getSalary(), staff1.getSalary());
        }).limit(1).forEach(System.out::println);
        System.out.println("------------------");

        //最低薪资的员工
        list.stream().sorted((staff1,staff2)->{
            return Double.compare(staff1.getSalary(), staff2.getSalary());
        }).limit(1).forEach(System.out::println);
        System.out.println("------------------");

        //根据部门统计员工
        Map<Course, List<Staff>> map = list.stream().collect(Collectors.groupingBy(Staff::getCourse));
        Set<Map.Entry<Course,List<Staff>>> entrySet = map.entrySet();
        for (Map.Entry<Course, List<Staff>> entry : entrySet) {
            Course key = entry.getKey();
            List<Staff> value = entry.getValue();
            System.out.println(key);
            System.out.println(Arrays.toString(value.toArray()));

        }

    }
}

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_LinkedList底层_09

迭代器实现原理

1 .Iterator迭代器实现原理

Iterator接口

boolean hasNext();//判断是否有可迭代的数据

E next();//获取下一个元素

package com.qf.iterator01;

//迭代器的接口
//作用:指定遍历数据的标准
public interface Iterator<E> {

	//判断是否有可迭代的数据
	boolean hasNext();
	
	//获取下一个元素
	E next();
	
	//删除功能(默认抛异常,意味着集合实现的迭代器可以选择是否有删除元素的功能)
	default void remove() {
   throw new UnsupportedOperationException("remove");
}
}

AbstractList 的抽象类, modCount是一个用于记录修改次数的变量 (外部操作数)

package com.qf.iterator01;

public abstract class AbstractList<E> {

	protected int modCount;//5s
}

ArrayList底层

这段代码是一个ArrayList类的实现,它继承了AbstractList类。ArrayList是一个动态数组,可以根据需要自动扩容。

下面是对代码的解析:

  1. elementData:是一个Object类型的数组,用于存储元素。
  2. size:表示元素的个数。
  3. DEFAULT_CAPACITY:默认容量,初始化ArrayList时使用的默认容量大小。
  4. DEFAULTCAPACITY_EMPTY_ELEMENTDATA:空内容的数组,用于初始化elementData。
  5. MAX_ARRAY_SIZE:最大数组长度,用于限制数组的最大容量。
  6. ArrayList():构造方法,初始化ArrayList对象。
  7. add(E e):向ArrayList中添加元素。在添加之前,通过ensureCapacityInternal方法确保容量足够,然后将元素添加到elementData数组中。
  8. ensureCapacityInternal(int minCapacity):确保容量足够。如果elementData数组为空,则将minCapacity设置为默认容量和minCapacity的较大值;然后调用ensureExplicitCapacity方法进行容量检查。
  9. ensureExplicitCapacity(int minCapacity):进行容量检查。如果需要扩容,则调用grow方法进行扩容。
  10. grow(int minCapacity):扩容方法。根据当前数组的容量,计算新的容量,然后通过Arrays.copyOf方法将元素复制到新的数组中。
  11. hugeCapacity(int minCapacity):计算巨大容量。如果minCapacity小于0,抛出内存溢出异常;否则,返回最大容量值。

这样,这段代码实现了一个基本的ArrayList类,具备添加元素和自动扩容的功能。

package com.qf.iterator01;

import java.util.Arrays;

public class ArrayList<E> extends AbstractList<E> {

	//元素容器
	public Object[] elementData;
	//元素个数
	private int size;//5
	//默认容量
	private static final int DEFAULT_CAPACITY = 10;
	//空内容的数组
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//最大数组长度
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE-8;
	
	public ArrayList() {
		elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	}
	
	public boolean add(E e) {
   ensureCapacityInternal(size + 1); 
   elementData[size++] = e;
   return true;
}

	//minCapacity - 1
private void ensureCapacityInternal(int minCapacity) {
   if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
   	//minCapacity - 10
       minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
   }
   ensureExplicitCapacity(minCapacity);
}

//minCapacity - 10
private void ensureExplicitCapacity(int minCapacity) {
   modCount++;

   if (minCapacity - elementData.length > 0)
       grow(minCapacity);
}

//minCapacity - 10
private void grow(int minCapacity) {
	
	//oldCapacity - 0
   int oldCapacity = elementData.length;
   //newCapacity - 0
   int newCapacity = oldCapacity + (oldCapacity >> 1);
   if (newCapacity - minCapacity < 0)
   	//newCapacity - 10
       newCapacity = minCapacity;
   
   if (newCapacity - MAX_ARRAY_SIZE > 0)
       newCapacity = hugeCapacity(minCapacity);
   
   // 扩容
   elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
   if (minCapacity < 0) // 长度小于0就报内存溢出
       throw new OutOfMemoryError();
   return (minCapacity > MAX_ARRAY_SIZE) ?
       Integer.MAX_VALUE :
       MAX_ARRAY_SIZE;
}
}

测试类test01

package com.qf.iterator01;

public class Test01 {
	/**
	 * 知识点:研究Iterator如何遍历
	 */
	public static void main(String[] args) {
		
		ArrayList<String> list = new ArrayList<>();
		
		list.add("AAA");
		list.add("BBB");
		list.add("CCC");
		list.add("DDD");
		list.add("EEE");
		
		for(Object obj : list.elementData){
			System.out.println(obj);
		}
		
	}
}

2. ListIterator底层

ListIterator的接口

package com.qf.iterator01;

public interface ListIterator<E> extends Iterator<E> {
   boolean hasNext();//判断是否有下一个可迭代的元素

   E next();//获取下一个元素

   boolean hasPrevious();//判断是否有上一个可迭代的元素

   E previous();//获取上一个元素

   int nextIndex();//获取下一个元素下标

   int previousIndex();//获取上一个元素下标

   void remove();//删除元素

   void set(E e);//修改元素

   void add(E e);//添加元素
}

iterator的接口

package com.qf.iterator01;

//迭代器的接口
//作用:指定遍历数据的标准
public interface Iterator<E> {

	//判断是否有可迭代的数据
	boolean hasNext();
	
	//获取下一个元素
	E next();
	
	//删除功能(默认抛异常,意味着集合实现的迭代器可以选择是否有删除元素的功能)
	default void remove() {
       throw new UnsupportedOperationException("remove");
   }
}
AbstractList的抽象类, 代码中定义了一个名为modCount的protected修饰的整型变量,它用于记录对集合的修改次数  。protected修饰符表示该变量可以被子类访问,但不能被其他包中的类访问。
package com.qf.iterator01;

public abstract class AbstractList<E> {

	protected int modCount;//5
}

ArrayList类

以下是对代码的解析:

  1. ArrayList(int initialCapacity):带有初始容量参数的构造方法。根据给定的初始容量创建一个ArrayList对象。
  2. size():返回ArrayList中元素的个数。
  3. add(int index, E element):在指定位置插入元素。首先进行下标的合法性检查,然后根据需要进行扩容,并通过System.arraycopy方法进行元素的移动,最后将新元素插入到指定位置。
  4. remove(Object o):移除指定元素。如果元素为null,则遍历ArrayList找到第一个为null的元素进行移除;如果元素不为null,则通过equals方法找到第一个与指定元素相等的元素进行移除。
  5. remove(int index):移除指定位置的元素。首先进行下标的合法性检查,然后通过System.arraycopy方法将元素进行移动,最后将最后一个元素设为null。
  6. set(int index, E element):将指定位置的元素替换为新的元素。首先进行下标的合法性检查,然后将新元素赋值给指定位置的元素,并返回被替换的旧元素。
  7. Iterator():获取迭代器的方法。
  8. ListIterator():获取ListIterator的方法。
  9. Itr内部类:实现了Iterator接口,用于实现ArrayList的迭代功能。使用游标cursor和遍历到的当前元素的下标lastRet来追踪迭代的状态。
  10. ListItr内部类:继承了Itr,实现了ListIterator接口,用于实现ArrayList的双向迭代功能。添加了hasPrevious()previous()nextIndex()previousIndex()set(E e)add(E e)等方法。

这样,这段代码实现了一个完整的ArrayList类,具备添加、删除、修改、迭代等功能。

package com.qf.iterator01;

import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;

public class ArrayList<E> extends AbstractList<E> {

	//元素容器
	public Object[] elementData;
	//元素个数
	private int size;//5
	//默认容量
	private static final int DEFAULT_CAPACITY = 10;
	//空内容的数组
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//空内容的数组
	private static final Object[] EMPTY_ELEMENTDATA = {};
	//最大数组长度
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE-8;
	
	public ArrayList() {
		elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	}
	
	public ArrayList(int initialCapacity) {
       if (initialCapacity > 0) {
           this.elementData = new Object[initialCapacity];
       } else if (initialCapacity == 0) {
           this.elementData = EMPTY_ELEMENTDATA;
       } else {
           throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
       }
   }
	
	public int size() {
		return size;
	}
	
	public boolean add(E e) {
       ensureCapacityInternal(size + 1); 
       elementData[size++] = e;
       return true;
   }
	
	//插入元素
	public void add(int index, E element) {
       rangeCheckForAdd(index);
       ensureCapacityInternal(size + 1);  // 判断是否扩容
       System.arraycopy(elementData, index, elementData, index + 1,
                        size - index);
       elementData[index] = element;
       size++;
   }
	
	private void rangeCheckForAdd(int index) {
       if (index > size || index < 0)
           throw new IndexOutOfBoundsException("下标越界:" + index);
   }
   
	//minCapacity - 1
   private void ensureCapacityInternal(int minCapacity) {
   	//使用无参构造创建ArrayList,第一次添加元素时进入的判断 -- 目的:确定初始化数组的长度
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
       	//minCapacity - 10
           minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
       }
       ensureExplicitCapacity(minCapacity);
   }
   
   //minCapacity - 10
   private void ensureExplicitCapacity(int minCapacity) {
       modCount++;

       if (minCapacity - elementData.length > 0)
           grow(minCapacity);
   }
   
   //minCapacity - 10
   private void grow(int minCapacity) {
   	
   	//oldCapacity - 0
       int oldCapacity = elementData.length;
       //newCapacity - 0
       int newCapacity = oldCapacity + (oldCapacity >> 1);
       if (newCapacity - minCapacity < 0)
       	//newCapacity - 10
           newCapacity = minCapacity;
       
       if (newCapacity - MAX_ARRAY_SIZE > 0)
           newCapacity = hugeCapacity(minCapacity);
       
       // 扩容
       elementData = Arrays.copyOf(elementData, newCapacity);
   }
   
   private static int hugeCapacity(int minCapacity) {
       if (minCapacity < 0) // 长度小于0就报内存溢出
           throw new OutOfMemoryError();
       return (minCapacity > MAX_ARRAY_SIZE) ?
           Integer.MAX_VALUE :
           MAX_ARRAY_SIZE;
   }
   
   public boolean remove(Object o) {
       if (o == null) {
           for (int index = 0; index < size; index++)
               if (elementData[index] == null) {
                   fastRemove(index);
                   return true;
               }
       } else {
           for (int index = 0; index < size; index++)
               if (o.equals(elementData[index])) {
                   fastRemove(index);
                   return true;
               }
       }
       return false;
   }
   
   private void rangeCheck(int index) {
       if (index >= size)
           throw new IndexOutOfBoundsException("index:" + index);
   }
   
   public E remove(int index) {
       rangeCheck(index);

       modCount++;
       E oldValue = elementData(index);

       int numMoved = size - index - 1;
       if (numMoved > 0)
           System.arraycopy(elementData, index+1, elementData, index,
                            numMoved);
       elementData[--size] = null; // clear to let GC do its work

       return oldValue;
   }
   
   @SuppressWarnings("unchecked")
   E elementData(int index) {
       return (E) elementData[index];
   }
   
   private void fastRemove(int index) {
       modCount++;
       int numMoved = size - index - 1;//计算数据迁移的次数
       if (numMoved > 0)
           System.arraycopy(elementData, index+1, elementData, index,
                            numMoved);
       elementData[--size] = null; 
   }
   
   public E set(int index, E element) {
       rangeCheck(index);//判断下标是否合法

       E oldValue = elementData(index);//通过下标获取到元素
       elementData[index] = element;//把新的元素赋值给指定下标的位置
       return oldValue;//返回被替换的值
   }
   
   //获取迭代器的方法
   public Iterator<E> Iterator(){
   	return new Itr();
   }
   
   public ListIterator<E> listIterator() {
       return new ListItr(0);
   }
   
   public ListIterator<E> listIterator(int index) {
       if (index < 0 || index > size)
           throw new IndexOutOfBoundsException("Index: "+index);
       return new ListItr(index);
   }
   
   
   
   public class Itr implements Iterator<E>{
   	
   	//游标 -- 判断是否有可迭代的数据的变量
   	int cursor; //0
   	//遍历到的当前元素的下标
       int lastRet = -1;//-1 
       //内部操作数
   	int expectedModCount = modCount;//5
   	
   	@Override
   	public boolean hasNext() {
   		return cursor != size;
   	}

   	@SuppressWarnings("unchecked")
		@Override
   	public E next() {
   		
   		checkForComodification();//判断内外部操作数使用一致
   		
   		int i = cursor;
           if (i >= size)
               throw new NoSuchElementException();
           Object[] elementData = ArrayList.this.elementData;
           if (i >= elementData.length)
               throw new ConcurrentModificationException();
           cursor = i + 1;
           return (E) elementData[lastRet = i];
   	}
   	
   	final void checkForComodification() {
   		if(expectedModCount != modCount){
   			throw new ConcurrentModificationException();
   		}
		}

		@Override
		public void remove() {
           if (lastRet < 0)
               throw new IllegalStateException();
           checkForComodification();

           try {
           	//迭代器中删除功能还是依赖于ArrayList的删除功能
               ArrayList.this.remove(lastRet);
               //把当前元素的下标赋值给游标
               cursor = lastRet;
               //将-1赋值给lastRet,说明该元素删除
               lastRet = -1;
               //将外部操作数赋值给内部操作数
               expectedModCount = modCount;
           } catch (IndexOutOfBoundsException ex) {
               throw new ConcurrentModificationException();
           }
       }

   }

   public class ListItr extends Itr implements ListIterator<E>{
   	
   	public ListItr(int index) {
   		cursor = index;
		}

		@Override
		public boolean hasPrevious() {
			return cursor != 0;
		}

		@SuppressWarnings("unchecked")
		@Override
		public E previous() {
			checkForComodification();//判断外部操作数和内部操作数是否一致
           int i = cursor - 1;
           if (i < 0)
               throw new NoSuchElementException();
           Object[] elementData = ArrayList.this.elementData;
           if (i >= elementData.length)
               throw new ConcurrentModificationException();
           cursor = i;
           return (E) elementData[lastRet = i];

		}

		@Override
		public int nextIndex() {
			return cursor;
		}

		@Override
		public int previousIndex() {
			return cursor-1;
		}

		@Override
		public void set(E e) {
			if (lastRet < 0)
               throw new IllegalStateException();
           checkForComodification();

           try {
               ArrayList.this.set(lastRet, e);//依赖于外部类ArrayList的set方法
           } catch (IndexOutOfBoundsException ex) {
               throw new ConcurrentModificationException();
           }
		}

		@Override
		public void add(E e) {
           checkForComodification();//判断外部操作数和内部操作数是否一致

           try {
               int i = cursor;
               ArrayList.this.add(i, e);
               cursor = i + 1;
               lastRet = -1;
               expectedModCount = modCount;//重新将外部操作数赋值给内部操作数
           } catch (IndexOutOfBoundsException ex) {
               throw new ConcurrentModificationException();
           }
       }		
   } 
}

3. LinkedList底层

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
   //外部操作数
   protected transient int modCount = 0;
   
   public ListIterator<E> listIterator() {
       return listIterator(0);
   }
}

public abstract class AbstractSequentialList<E> extends AbstractList<E> {
   
   public Iterator<E> iterator() {
       return listIterator();
   }
   
   public ListIterator<E> listIterator() {
       return listIterator(0);
   }
   
   public ListIterator<E> listIterator(final int index) {
       rangeCheckForAdd(index);

       return new ListItr(index);
   }
   
}

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>{
   //元素个数
   transient int size = 0;
   //开始节点
   transient Node<E> first;
	//结束节点
   transient Node<E> last;
   
   public LinkedList() {
   }
   
   public boolean add(E e) {
       linkLast(e);
       return true;
   }
   
   void linkLast(E e) {
       final Node<E> l = last;
       final Node<E> newNode = new Node<>(l, e, null);
       last = newNode;
       if (l == null)
           first = newNode;
       else
           l.next = newNode;
       size++;
       modCount++;
   }
   
   //index - 0
   public ListIterator<E> listIterator(int index) {
       checkPositionIndex(index);
       return new ListItr(index);
   }
   
   //index - 0
   private void checkPositionIndex(int index) {
       if (!isPositionIndex(index))
           throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
   }
   
   private boolean isPositionIndex(int index) {
       return index >= 0 && index <= size;
   }
   
   //获取指定下标上的节点对象
   //index - 0
   Node<E> node(int index) {

       if (index < (size >> 1)) {
           Node<E> x = first;
           for (int i = 0; i < index; i++)
               x = x.next;
           return x;
       } else {
           Node<E> x = last;
           for (int i = size - 1; i > index; i--)
               x = x.prev;
           return x;
       }
   }
   
   //节点类
   private static class Node<E> {
       E item; ---------- 元素
       Node<E> next; ---- 下一个节点的引用地址
       Node<E> prev; ---- 上一个节点的引用地址

       Node(Node<E> prev, E element, Node<E> next) {
           this.item = element;
           this.next = next;
           this.prev = prev;
       }
   }
   
   private class ListItr implements ListIterator<E> {
       private Node<E> lastReturned;//第一个节点
       private Node<E> next;//获取第三个节点
       private int nextIndex;//2
       private int expectedModCount = modCount;//3

       ListItr(int index) {
           next = (index == size) ? null : node(index);
           nextIndex = index;
       }

       public boolean hasNext() {
           return nextIndex < size;
       }

       public E next() {
           checkForComodification();//外部操作数和内部操作数是否一致
           if (!hasNext())
               throw new NoSuchElementException();

           lastReturned = next;//lastReturned - 第二个节点
           next = next.next;//获取第三个节点
           nextIndex++;
           return lastReturned.item;
       }

       public boolean hasPrevious() {
           return nextIndex > 0;
       }

       public E previous() {
           checkForComodification();
           if (!hasPrevious())
               throw new NoSuchElementException();

           lastReturned = next = (next == null) ? last : next.prev;
           nextIndex--;
           return lastReturned.item;
       }

       public int nextIndex() {
           return nextIndex;
       }

       public int previousIndex() {
           return nextIndex - 1;
       }

       public void remove() {
           checkForComodification();
           if (lastReturned == null)
               throw new IllegalStateException();

           Node<E> lastNext = lastReturned.next;
           unlink(lastReturned);
           if (next == lastReturned)
               next = lastNext;
           else
               nextIndex--;
           lastReturned = null;
           expectedModCount++;
       }

       public void set(E e) {
           if (lastReturned == null)
               throw new IllegalStateException();
           checkForComodification();
           lastReturned.item = e;
       }

       public void add(E e) {
           checkForComodification();
           lastReturned = null;
           if (next == null)
               linkLast(e);
           else
               linkBefore(e, next);
           nextIndex++;
           expectedModCount++;
       }

       final void checkForComodification() {
           if (modCount != expectedModCount)
               throw new ConcurrentModificationException();
       }
   }
}LinkedList<String> list = new LinkedList<>();

list.add("张三");
list.add("李四");
list.add("王五");

2023年6月29日,测评机试题,Iterator底层,ListIterator底层,LinkedList底层_LinkedList底层_10

标签:index,return,LinkedList,Iterator,int,elementData,new,public,底层
From: https://blog.51cto.com/u_15098423/6585064

相关文章

  • 底层开发代码规范
    前言:此文主要针对stm32系列工程,规范代码可以加速开发速度和dbg速度源文件和头文件格式规范 这里给出比较规范的源文件和头文件应该大致具备的一些格式。/*Includes---------------------------------------------------------------------*/#include<name.h>/*Privatet......
  • Iterator和LlistIterator迭代器的使用及底层原理:
    先来看下面的示例:publicclassDemo{publicstaticvoidmain(String[]args)throwsIOException{List<String>list=newLinkedList<>();list.add("唐僧");list.add("孙悟空");list.add("猪八戒")......
  • iterator
       ......
  • HashMap与ConcurrentHashMap底层分析
    一.红黑树的要点:在介绍HashMap与ConcurrentHashmap底层原理之前我们首先介绍红黑树的知识点,他是我们JDK1.8后为HashMap与ConcurrentHashMap引入的优化的数据结构。1.1红黑树的特点:1.每一个结点不是红色就是黑色2.不可能有连接在一起的红色结点,也即是如果有一个结点是红色,则......
  • 由Python历史「解密」Python底层逻辑
    一次纯粹的hackingPython的作者,GuidovonRossum,荷兰人。1982年,Guido从阿姆斯特丹大学获得了数学和计算机硕士学位。尽管,他算得上是一位数学家,但他更加享受计算机带来的乐趣,热衷于做任何和编程相关的活儿。80年代,掀起了个人电脑浪潮,但受限于个人电脑配置低,所有的编译器的核心是做优......
  • ReentrantLock底层实现原理
    ReentrantLock底层的源码分析:本小节我们将由浅入深的讲解ReentrantLock的底层源码,其中会附带有源码的分析:1.自己实现简易的ReentrantLock锁:在多线程的并发的操作当中,我们需要通过锁机制来实现多个线程互斥的访问特定的资源从而避免并发下的操作问题。我们可以先来看一下Reentra......
  • 【嵌入式通信】嵌入式通信的底层逻辑
    本文主要是对B站视频【蛋饼嵌入式】嵌入式通信的底层逻辑 的总结,视频内容帮我进一步认识了几个问题:同步通信和异步通信的区别、DDR、NRZ编码的意义等。0、计算机网络通信框架ISO国际标准化组织在上世界70年代末,把计算机网络通信的整个框架描述成了一个七层的模型,称之为OSI......
  • hashMap和hashTable的区别以及HashMap的底层原理?
    hashMap和hashTable的区别?1、继承的父类不同HashTable继承Dictionary类,而hashMap继承了AbstractMap类,但是二者都实现了map接口。2、线程安全性不同 Hashtable线程安全,因为它每个方法中都加入了Synchronize。HashMap是线程不安全的。1HashMap底层是一个Entry数组,当发生hash......
  • ArrayList和LinkedList的区别详解
    感谢巨人的肩膀,原作者:https://blog.csdn.net/qing_gee/article/details/108841587/ArrayList和LinkedList有什么区别,是面试官非常喜欢问的一个问题。可能大部分小伙伴和我一样,能回答出“ArrayList是基于数组实现的,LinkedList是基于双向链表实现的。”关于这一点,我之前的......
  • 腾讯技术团队最新出品,Android Framework系统框架底层原理解密
    今年以来,Android就业形势愈发严峻,各公司对开发人员的要求也是逐渐提高,在筛选Android程序员的时候也越来越看重其对于底层的理解和思考。作为一个AndroidAPP开发者,我们也不能当温水里的青蛙,必须对Android系统的组成和AndroidFramework的层次架构有所了解,才能突破和进阶。在这里就......