集合框架二

1.List 概念介绍

有序集合(也称为 序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。 有序集合, List 集合有一个下标 ( 索引 ) ,我们可以根据索引来操作集合中的元素。 List 接口是 Collection 接口的子接口。 实现了 List 接口的集合类中是有序的,且 允许重复。 List 集合中的元素都对应一个整数型的序号,记载了其在集合中的位置,可以根据序号存取集合中的元素。

2.常用的方法介绍

2.1 重复元素和null 在 List 接口中是可以存储重复元素和 null 值的。

2.2 添加功能

Collection 接口中提供的功能。

boolean add(E e)
//确保此集合包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
//将指定集合中的所有元素添加到此集合(可选操作)。

List 接口中 新增的功能。

void add(int index, E element)
// 将指定的元素插入此列表中的指定位置(可选操作)
boolean addAll(int index, Collection<? extends E> c)
//将指定集合中的所有元素插入到此列表中的指定位置(可选操作)

import java.util.ArrayList;
import java.util.List;
 
public class ListDemo02 {
 
    /**
     * List接口
     * @param args
     */
    public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(1); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
        System.out.println(list1);
 
        list1.add(2,"张三");
        System.out.println(list1);
        List list2 = new ArrayList();
        list2.add("小明"); // 添加第一个元素
        System.out.println(list2);
        list2.add(0,"小李"); // 在集合的第一个位置添加一个元素
        System.out.println(list2);
        list2.addAll(1,list1); // 将list1集合中的元素插入到 list2集合的第一个元素之后
        System.out.println(list2);
    }
}

 

2.3 删除功能

肯定具有 Collection 接口中定义的删除方法。

void clear()
// 从此集合中删除所有元素(可选操作)。
boolean remove(Object o)
// 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)
// 删除指定集合中包含的所有此集合的元素(可选操作)。

List 接口中特有的删除方法。

 

E remove(int index)
// 删除该列表中指定位置的元素(可选操作)。
2.4 修改功能

在 Collection 接口中针对修改并不友好,但是在 List 接口中修改就非常的方便了,我们可以同下标可以直接来修改。

E set(int index, E element)
用指定的元素(可选操作)替换此列表中指定位置的元素。

 

import java.util.ArrayList;
import java.util.List;
 
public class ListDemo04 {
    public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(1); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
        System.out.println(list1);
        list1.set(1,666);
        System.out.println(list1);
    }
}

 

2.5 遍历功能

遍历获取集合中的相关元素,当然肯定可以使用 Collection 接口中定义的方式及 foreach 循环。

Object[] toArray()
// 返回一个包含此集合中所有元素的数组。
Iterator<E> iterator()
// 返回此集合中的元素的迭代器

 

还可以使用 List 接口中定义的新的方式,接口下标通过普通 for 循环来实现。

 public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(1); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
 
        // 循环获取集合中的元素
        // System.out.println(list1.get(2));
        for(int i = 0 ; i < list1.size() ; i ++){
            System.out.println(list1.get(i));
        }
    }
}

 总遍历方法

public class Demo4 {
    public static void main(String[] args) {
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(1);
        list1.add(3);
        list1.add(5);
        list1.add(null);
        System.out.println(list1);

        //for循环
        for (int i = 0; i < list1.size(); i++) {
            System.out.println(list1.get(i));
        }
        //foreach
        Object[] objects = list1.toArray();
        for (Object o : objects) {
            System.out.println(o);
        }
        //Iterator
        Iterator it = list1.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}

迭代功能在 List 接口中也有扩展。

 

ListIterator<E> listIterator()
//返回列表中的列表迭代器(按适当的顺序)。
ListIterator<E> listIterator(int index)
//从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。

2.6 其他功能

 

E get(int index)
// 返回此列表中指定位置的元素。
 
int indexOf(Object o)
// 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o)
// 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
List<E> subList(int fromIndex, int toIndex)
// 返回此列表中指定的 fromIndex (含)和 toIndex之间的视图
 public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(3); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
        list1.add("张三");
        list1.add("李四");
        list1.add(3);
        System.out.println(list1.indexOf(3));
        System.out.println(list1.lastIndexOf(3));
 
        System.out.println(list1.subList(2,4));
 
    }
}
3.ListIterator接口

ListIterator 接口是 Iterator 接口的子接口,在 Iterator 正向迭代的基础上扩展了逆向迭代的操作。

public class Demo07 {
    public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(3); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
        list1.add("张三");
        list1.add("李四");
        list1.add(3);
        // 获取ListIterator接口实例
 
        ListIterator li = list1.listIterator();
        System.out.println(li.previousIndex()+ ":" +li.hasPrevious()); // 游标指向了第一个元素的左侧
        while(li.hasNext()){ // 正向迭代  判断是否有下一个元素
            System.out.println(li.nextIndex() + ":" + li.next());
        }
        //System.out.println(li.previousIndex()+ ":" +li.hasPrevious()); // 游标指向了最后一个元素的右侧
        //System.out.println(li.previousIndex()+ ":" +li.hasPrevious()); // 游标指向了最后一个元素的右侧
        System.out.println("***************************");
        while(li.hasPrevious()){
            System.out.println(li.previousIndex() + ":" + li.previous());
        }
    }

 

4.List接口的小结
4.1 List接口遍历方式

toArray

Iterator

foreach

普通的 for 循环

ListIterator

4.2 List接口去除重复元素

方式一:创建一个新的集合来存储去除重复元素。

public class Demo08 {
    public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(3); // 存储重复的元素
        list1.add(2);
        list1.add(null);  // 添加 null
        list1.add("张三");
        list1.add("李四");
        list1.add(3);
        // 获取ListIterator接口实例
        System.out.println(list1);
        List list2 = new ArrayList();
        for(Object o : list1){ // 遍历原来的集合
            if(!list2.contains(o)){ // 判断新的集合中是否包含的有遍历的元素
                list2.add(o); // 新的集合中不含有该元素,就直接添加进新的集合中
            }
        }
        System.out.println(list2);
 
    }
}

 方式二:在原有集合的基础上使用选择排序的思想来去除重复元素【单纯的准备面试】

 

public class ListDemo09 {
    public static void main(String[] args) {
        // 获取一个List接口对象
        List list1 = new ArrayList();
        list1.add(1);
        list1.add(3); // 存储重复的元素
        list1.add(3);
        list1.add(3);
        list1.add(3);
        list1.add("aa");  // 添加 null
        list1.add("张三");
        list1.add("李四");
        list1.add(3);
        // 获取ListIterator接口实例
        System.out.println(list1);
 
        for(int i = 0 ; i < list1.size() - 1;i++){
            for(int j = i + 1; j < list1.size() ; j++){
                if(list1.get(i).equals(list1.get(j))){
                    list1.remove(j);
                    j--;
                }
            }
        }
        System.out.println(list1);
 
    }
}

 

5.List接口的相关实现类
5.1 ArrayList

可调整大小的数组的实现 List 接口。 实现所有可选列表操作,并允许所有元素,包括 null 。除了实现List 接口 之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。 (这个类是大致相当于 Vector , 不同之处在于它是不同步的)。

5.1.1 ArrayList的特点

特点:

  1. 底层的数据结构是数组。

  2. 能够存储 null 值。

  3. 线程不安全,效率高。

  4. 底层是数组结构,那么就意味着查询和修改的效率高,而增加和删除的效率就低了。

  5. 有索引,能够方便的检索。

  6. 元素是可以重复的,我们可以自己通过选择排序法去重。

  7. 不可排序。

注: ArrayList 中常用的方法全部来自于 父类 Collection 、 List 、 Object 。我们都介绍过,所以在次就不再重复了。

课堂案例:

存储多个员工信息(包括工号、姓名、年龄,入职时间),逐条打印所有员工姓名,并输出员工的个数 使用 ArrayList 存储数据 元素个数不确定 要求获得元素的实际个数 按照存储顺序获取并打印元素信息

public class ArrayListDemo02 {
 
    /**
     * 存储多个员工信息(包括工号、姓名、年龄,入职时间),逐条打印所有员工姓名,并输出员工的个数
     * 使用ArrayList存储数据
     * 元素个数不确定
     * 要求获得元素的实际个数
     * 按照存储顺序获取并打印元素信息
     * @param args
     */
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        for(int i = 0 ; i < 10 ; i ++){
            Employee e = new Employee("emp"+i,"张三"+i,10+i,new Date());
            list.add(e);
        }
        System.out.println(list);
        // 逐条打印员工的信息
        for (Object o:list) {
            if(o instanceof  Employee){
                Employee e = (Employee) o;
                System.out.println(e);
            }
        }
        // 员工的个数
        System.out.println("员工的个数是:" + list.size());
    }
}
 
/**
 * 员工类
 */
class Employee{
 
    private String empNo; // 员工编号
 
    private String empName; // 员工姓名
 
    private Integer age; // 在成员变量中如果是基本数据类型 我们推荐使用包装类声明
 
    private Date entryDate; // 入职时间
 
    public Employee(String empNo, String empName, Integer age) {
        this.empNo = empNo;
        this.empName = empName;
        this.age = age;
    }
 
    public Employee(String empNo, String empName, Integer age, Date entryDate) {
        this(empNo,empName,age);
        this.entryDate = entryDate;
    }
 
    public String getEmpNo() {
        return empNo;
    }
 
    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }
 
    public String getEmpName() {
        return empName;
    }
 
    public void setEmpName(String empName) {
        this.empName = empName;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
    public Date getEntryDate() {
        return entryDate;
    }
 
    public void setEntryDate(Date entryDate) {
        this.entryDate = entryDate;
    }
 
    @Override
    public String toString() {
        return "Employee{" +
                "empNo='" + empNo + '\'' +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", entryDate=" + entryDate +
                '}';
    }
}
5.1.2 ArrayList原理分析

ArrayList 的本质就是 动态数据,动态扩容 初始的属性了解

/**
* 集合默认的容量 10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认容量的空的数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 集合中真实的存储数据的 数组
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 集合中的元素的个数,注意 不是数组的长度!!!!
* @serial
*/
private int size;

 5.1.3 ArrayList作业 ArrayList 集合练习: ( 1 )创建一个 Person 类,添加属性 :name,age; 封装这些属性并分别设置各个属性的方法。 ( 2 )根据用户输入的对象个数创建 Person 对象,接收用户在控制台上输入的每个对象的信息。 ( 注意,将有些Person 对象的名字和年龄设置相同 )。 ( 3 )创建一个 ArrayList 集合,将 Person 对象添加到 ArrayList 集合中。 ( 4 )使用迭代器迭代输出该 List 集合。 ( 5 )写一个方法,可以去除 ArrayList 集合中重复的 Person 对象。姓名和年龄相同视为重复的 Person 对象。

Person 类

public class Person {private String name;
 
private Integer age;
 
public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
}
 
public String getName() {
    return name;
}
 
public void setName(String name) {
    this.name = name;
}
 
public Integer getAge() {
    return age;
}
 
public void setAge(Integer age) {
    this.age = age;
}
 
@Override
public String toString() {
    return "Person{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}


public class ArrayListHomeWork {public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    System.out.println("请输入Person对象的个数:");
    int number = in.nextInt();
    System.out.println("Person的姓名:");
    String name = in.next();
    System.out.println("Person的年龄:" );
    Integer age = in.nextInt();
    // 创建一个ArrayList集合
    ArrayList list = new ArrayList();
    for(int i = 0 ; i < number ; i ++){
        Person person = new Person(name,age);
        // 将创建的Person对象添加到list集合中去
        list.add(person);
    }
    // 使用迭代器 输出集合
    printIteratorList(list);
    System.out.println("*************");
    // 移除重复的元素
    removeRepetitionElement(list);
    // 使用迭代器 输出集合
    printIteratorList(list);
}
 
/**
 * 移除重复元素
 *    通过选择排序的方式来移除重复的元素
 *    姓名和年龄相同表示是重复的元素
 * @param list
 */
public static void removeRepetitionElement(ArrayList list){
    for(int i = 0 ; i < list.size() - 1 ; i ++){
        for(int j = i + 1 ; j < list.size() ; j ++){
            Person p1 = (Person) list.get(i);
            Person p2 = (Person)list.get(j);
            if(p1.getName().equals(p2.getName()) && p1.getAge() == p2.getAge()){
                list.remove(j);
                j--;
            }
        }
    }
}
 
/**
 * 迭代输出集合中的信息
 * @param list
 */
    private static void printIteratorList(ArrayList list) {
        ListIterator listIterator = list.listIterator();
        while(listIterator.hasNext()){
            Object next = listIterator.next();
            if(next instanceof  Person){
                Person p = (Person) next;
                System.out.println(p);
            }
        }
    }
}

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值