Java SE核心API(5) —— 集合操作(线性表)

版权声明:本文为博主原创文章,遵循GPL开源协议精神,转载请注明出处。 https://blog.csdn.net/Robot__Man/article/details/79249898

一、ArrayList类和LinkedList类

  List接口是Collection的子接口,用于定义线性表数据结构。可以将List理解为存放对象的数组,只不过其元素个数可以动态的增加或减少。
  List接口的两个常见实现类为ArrayList和LinkedList,分别用动态数组和链表的方式实现了List接口。可以认为ArrayList和LinkedList的方法在逻辑上完全一样,只是在性能上有一定的差别,ArrayList更适合于随机访问而LinkedList更适合于插入和删除。在性能要求不是特别苛刻的情形下可以忽略这个差别。


二、get()、set()

  List除了继承Collection定义的方法外,还根据其线性表的数据结构定义了一系列方法,其中最常用的就是基于下标的get和set方法。

package day04;

import java.util.ArrayList;
import java.util.List;

/**
*java.util.List
*可重复集,并且有序。
*特点是可以根据下标操作元素。
*常用实现类:
*ArrayList:使用数组实现,查询更快
*LinkedList:使用链表实现,增删更快(首尾增删效果明显)
*/
public class ListDemo1{
    public static void main(String[] args){
        /*
        *E set(int index,E e)
        *将给定元素设置到指定位置上,返回值为
        *原位置的元素。所以是替换元素操作。
        */
        List<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        System.out.println(list);

        String old = list.set(1, "2");
        System.out.println(list);
        System.out.println("old:"+old);

        //list.set(4, "five");这样做下标越界

        /*
        *E get(int index)
        *获取给定下标对应的元素
        */
        //获取第三个元素
        String str = list.get(2);
        System.out.println(str);

        for (int i = 0;i < list.size();i++){
            str = list.get(i);
            System.out.println(str);
        }
    }
}

  set方法将指定索引位置设置为指定的元素,其返回值为未设置前此位置的元素。鉴于set方法这样的设计,可以使用此语句实现将list中第i个和第j个元素交换的功能:
  list.set(i, list.set(j, list.get(i)));


三、add()、remove()

  List根据下标的操作还支持插入与删除操作。
  void add(int index,E e),将给定的元素插入到指定位置,原位置及后续元素都顺序向后移动。
  E remove(int index),删除指定位置的元素,并将被删除的元素返回。

package day04;

public class ListDemo2{
    public static void main(String[] args){
        List<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        System.out.println(list);

        list.add(1, "2");
        System.out.println(list);

        String old = list.remove(2);
        System.out.println(list);
        System.out.println("old:"+old);
    }
}

四、subList()

  List的subList方法用于获取子List。
  List<E> subList(int fromIndex,int toIndex),fromIndex和toIndex是截取子List的首尾下标(前包括,后不包括)。
  需要注意的是,subList获取的List与原List占用相同的存储空间,对子List的操作会影响原List。

package day04;

/**
*取子集
*List subList(int start,int end)
*获取当前集合中指定范围内的子集。同样含头不含尾。
*/
public class ListDemo3{
    public static void main(String[] args){
        List<Integer> list = new ArrayList<Integer>();

        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);
        }
        System.out.println(subList);
        /*
        *对子集的修改,就是修改原集合相应内容
        */
        System.out.println(list);

        /*
        *删除集合中2-8的元素
        */
        list.subList(2,9).clear();
        System.out.println(list);
    }
}

五、集合转换为数组

  List的toArray方法用于将集合转换为数组。但实际上该方法是在Collection中定义的,所以所有的集合都具备这个功能。其有两个方法:
  Object[] toArray()<T>T[] toArray(T[] a)
  其中第二个方法是比较常用的,我们可以传入一个指定类型的数组,该数组的元素类型应与集合的元素类型一致。返回值则是转换后的数组,该数组会保存集合中所有的元素。

package day04;

import java.util.ArrayList;
import java.util.Collection;

/**
*集合转换为数组,对List和Set皆可用。
*/
public class CollectionToArrayDemo{
    public static void main(String[] args){
        Collection<String> c = new ArrayList<String>();
        c.add("one");
        c.add("two");
        c.add("three");
        c.add("four");

        /*
        *集合提供了一个方法toArray,可以将当前集合转换为数组。
        */
        //Object[] array = c.toArray();
        /*
        *若给定的数组大小可用(数组可以存放集合所有元素)时,则使用该数
        *组,若不可用,会自动创建一个与给定数组同类型的数组。
        */
        String[] array = c.toArray(new String[c.size()]);
        System.out.println("len:"+array.length);
        for (String str:array){
            System.out.println(str);
        }
    }
}

六、数组转换为集合

  Arrays类中提供了一个静态方法asList,使用该方法我们可以将一个数组转换为对应的List集合。其方法定义为:static <T>List<T> asList<T...a>。返回的List的集合元素类型由传入的数组的元素类型决定。
  需要注意的是,返回的集合我们不能对其增删元素,否则会抛出异常。并且对集合的元素进行修改会影响数组对应的元素。

package day04;

import from java.util.List;

/**
*数组转换为集合
*需要注意,转换只能转换为List集合
*使用的是数组的工具类Arrays的静态方法asList
*只能转换为List集合的主要原因是:Set不能存放重复元素,所以若转换为Set集合可能出现
*丢失元素的情况。
*/
public class ArrayToListDemo{
    public static void main(String[] args){
        String[] array = {"one","two","three","four"};
        List<String> list = Arrays.asList(array);
        System.out.println(list);

        /*
        *向集合中添加一个元素
        *实际上下面的代码会抛出异常,因为该集合是由数组转换来的,那么该
        *集合就表示原来的数组,所以对集合的操作就是对数组的操作。那么添
        *加元素会导致原数组扩容,那么就不能表示原来的数组了,所以不允许
        *向该集合添加元素。
        */
        //list.add("five");
        //System.out.println(list);

        //修改集合元素,数组元素也会改变
        list.set(1, "2");
        System.out.println(list);
        //输出数组元素
        for (String str:array){
            System.out.println(str);
        }

        /*
        *若希望增删元素,需要另创建一个集合
        */
        //List<String> list1 = new ArrayList<String>();
        //list1.addAll(list);
        /*
        *所有的集合都提供了一个带有Collection类型参数的构造方法。
        *该构造方法称为:复制构造器。
        *作用是在创建当前集合的同时,集合中包含给定集合中的所有元素。
        */
        List<String> list1 = new ArrayList<String>(list);
        list1.add("five");
        System.out.println(list1);
    }
}

七、List排序

  Collections是集合的工具类,它提供了很多便于我们操作集合的方法,其中就有用于集合排序的sort方法。
  该方法定义为:void sort(List<T> list),该方法的作用是对给定的集合元素进行自然排序。

7.1、Collections.sort方法实现排序

package day04;

/**
*排序集合元素
*排序集合使用的是集合的工具类Collections的静态方法sort。
*排序仅能对List集合进行。因为Set部分实现类是无序的。
*/
public class SortListDemo{
    public static void main(String[] args){
        List<Integer> list = new ArrayList<Integer>();

        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);
    }
}

7.2、Comparable

  Collections的sort方法是对集合元素进行自然排序,那么两个元素对象之间就一定要有大小之分。这个大小之分是如何界定的?实际上,在使用Collections的sort排序的集合元素都必须是Comparable接口的实现类,该接口表示其子类是可比较的,因为实现该接口必须重写抽象方法:
  int compareTo(T t),该方法用于使当前对象与给定对象进行比较:
  若当前对象大于给定对象,那么返回值应为>0的整数。
  若小于给定对象,那么返回值应为<0的整数。
  若两个对象相等,则应返回0。

package day05;
/**
 * 该类用于作为集合的元素
 * @author xxx
 *
 */
public class Point implements Comparable<Point>{
    private int x;
    private int y;

    public Point(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public String toString() {
        return "("+x+","+y+")";
    }

    /*
     * 当实现了Comparable接口后,需要重写下面的方法,该方法的作用是定义当前对象与给定参数对象比较大小的规则。
     * 返回值为一个int值,该值表示大小关系,它不关注具体的值是多少,而关注的是取值范围。
     * 当返回值>0时:当前对象比参数对象大
     * 当返回值<0时:当前对象比参数对象小
     * 当返回值=0时:两个对象相等
     */
    public int compareTo(Point o) {
        /*
         * 比较规则,点到原点的距离长的大
         */
        int len = this.x * this.x + this.y * this.y;
        int olen = o.x * o.x + o.y * o.y;
        return len - olen;
    }
}
package day05;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 排序自定义类型元素的集合
 * @author xxx
 *
 */
public class SortListDemo1 {
    public static void main(String[] args) {
        List<Point> list = new ArrayList<Point>();
        list.add(new Point(1, 2));
        list.add(new Point(3, 4));
        list.add(new Point(5, 6));
        list.add(new Point(1, 1));
        list.add(new Point(9, 10));
        list.add(new Point(0, 1));

        System.out.println(list);

        /*
         * sort方法要求集合元素必须实现Comparable接口,该接口用于规定实现类是
         * 可以比较的。其中一个抽象方法是用来定义比较大小的规则。
         * 
         * 我们想使用sort方法排序集合,但是该方法要求我们的集合元素必须实现Comparable接口并且定义比较规则,
         * 这种我们想使用某个功能,而它要求我们修改程序的现象称为“侵入性”。修改的代码越多,侵入性越强,越不利于
         * 程序的扩展。
         */
        Collections.sort(list);
        System.out.println(list);
    }
}

7.3、Comparator

  一旦Java类实现了Comparable接口,其比较逻辑就已经确定;如果希望在排序的操作中临时指定比较规则,可以采用Comparator接口回调的方式。
  Comparator接口要求实现类必须重写其定义的方法:int compare(T o1,T o2),该方法的返回值要求:
  若o1大于o2,则返回值应>0。
  若o1小于o2,则返回值应<0。
  若o1等于o2,则返回值应为0。

package day05;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 自定义比较规则
 * @author xxx
 *
 */
public class SortListDemo2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();

        list.add("jerry");
        list.add("tom");
        list.add("rose");
        list.add("merry");
        list.add("jack");
        list.add("james");

        System.out.println(list);
        /*
         * 重载的sort方法要求传入一个额外的比较器,该方法不再要求集合元素必须实现Comparable接口,
         * 并且也不再使用集合元素自身的比较规则排序了,而是根据给定的这个额外的比较器的比较规则对集合元素
         * 进行排序。
         * 实际开发中也推荐使用这种方式排序集合元素,若集合元素是自定义的。
         * 创建比较器时也推荐使用匿名内部类的形式。
         */
        Comparator<String> com = new Comparator<String>() {
            public int compare(String o1,String o2) {
                return o1.length() - o2.length();
            }
        };
        Collections.sort(list,com);
        System.out.println(list);
    }
}

猜你喜欢

转载自blog.csdn.net/Robot__Man/article/details/79249898