Javase_1.4.1 数组与集合

JavaSE 1.4.1 数组与集合:

数组:

动态初始化指定长度,静态初始化指定内容。数组一旦创建,长度无法改变。

int[] arrayDynamic = new int[100]; //动态初始化

int[] arrayA = {10,20,30};  //静态省略,不能拆分

int[] arrayA1 = new int[]{10,20,30}; //静态初始化

//静态初始化拆分
int[] arrayA2;
arrayA2 = new int[]{10,20,30}; 

动态初始化数组时,整数类型初始化为0,浮点0.0,字符\u0000,布尔False,引用null。(静态初始化时也有默认值过程,但是马上就赋值了)

  • 数组索引越界异常: array index out of bounds exception
  • 空指针异常: 没有new创建。数组是引用类型。null pointer exception
对象数组:
Person[] array = new Person[3];
array[0] = new Person("lvlvsun",10);
array[1] = new Person("zly",20);
array[2] = new Person("leakyRelu",30);
System.out.println(array[0].getName());

缺点:一旦创建,程序运行期间长度无法改变,所以可以采用ArrayList集合。


数组的元素反转:

双指针

for (int min = 0, max = array.length - 1 ; min < max; min++, max--) {
    int temp = array[max];
    array[max] = array[min];
    array[min] = temp;
}
数组的元素遍历:

fori和foreach(迭代器iterator,稍后会有)

int[] array = new int[]{...};
for (int i = 0; i < array.length; i++) {
}
for (int i : array) {
}

二维数组:

各行长度不同,叫锯齿数组

int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
arr.length();//获取数组x长度
arr[0].length...//数组y方向长度,可以用嵌套for循环处理二维数组

Arrays类:

Arrays.sort();
Arrays.parallelsort();:多处理器排序
Arrays.binarySearch(array,number); 二分查找
Arrays.copyOf(array,len):
sort(String)会按照字母升序。但如果sort自定义类,那么这个自定义类需要实现Comparable接口或者Comparator接口的支持。

方法使用

public static String toString(array);: 将参数数组转换成默认格式的字符串,如例
public static void sort(array);: 升序,无返回值,别的类型也可以排序。

int[] intArray = {10, 20, 30};
// 将int[]数组按照默认格式变成字符串
String intStr = Arrays.toString(intArray);
System.out.println(intStr); // [10, 20, 30]

int[] array1 = {2, 1, 3, 10, 6};
Arrays.sort(array1);
System.out.println(Arrays.toString(array1)); // [1, 2, 3, 6, 10]

String[] array2 = {"bbb", "aaa", "ccc"};
Arrays.sort(array2);
System.out.println(Arrays.toString(array2)); // [aaa, bbb, ccc]

字符串倒序打印
    String str = "asv76agfqwdfvasdfvjh";
    // 必须是一个数组,才能用Arrays.sort方法
    // String --> 数组,用toCharArray
    char[] chars = str.toCharArray();
    Arrays.sort(chars);

    // 需要倒序遍历
    for (int i = chars.length - 1; i >= 0; i--) {
        System.out.println(chars[i]);
    } 


集合:推荐学习数据结构

在这里插入图片描述

Collection接口:

public interface Collection<E> extends Iterable<E>

数组的长度是固定的。集合的长度是可变的。

集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map

List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。

在这里插入图片描述

针对Collection集合我们到底使用谁呢?

唯一吗?

  • ​ 是:Set

    排序吗?

    • 是:TreeSet
    • 否:HashSet
      如果你知道是Set,但是不知道是哪个Set,就用HashSet。
  • ​ 否:List

    要安全吗?

    • 是:Vector
    • 否:ArrayList或者LinkedList
      查询多:ArrayList
      增删多:LinkedList

​ 如果你知道是List,但是不知道是哪个List,就用ArrayList。

Collection常用功能:
  • public boolean add(E e): 把给定的对象添加到当前集合中 。
  • public void clear() :清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。

Iterator迭代器

public interface Iterable<T>

public interface Iterator<E>

迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator<String> itera = coll.iterator();
//  泛型指的是 迭代出 元素的数据类型
while(itera.hasNext()){ //判断是否有迭代元素
    String str = itera.next();//获取迭代出的元素
    System.out.println(str);
}
迭代器原理:

获取实现类对象时,指针指向集合的-1索引,迭代器的next取出元素并操作指针向后移动一位。

增强for循环:

for(元素的数据类型 变量 : Collection集合or数组){ }

用于遍历元素,不能增删操作。会抛出并发修改异常。ConcurrentModificationException

泛型:可以在类或方法中使用未知的类型。类型参数化

协变:

数组的协变,内部协变。
子类的数组对象可以使用父类的引用数组取引用。
集合泛型就没有协变功能。

泛型的使用

在JDK5之后,新增的泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样使用API的时候也变得更为简洁,并得到了编译时期的语法检查。
泛型不能应用在基本类型,需要使用包装类

在类中使用泛型
public class GenericClass<T,E> {
   	public void doing(T person){
   	}
   	public T read(E element){
   		return null;
   	}
}
在方法中使用泛型
public <T> T test(T t){
	return null;
}

public static <T> void sort(T[] a, Comparator<? super T> c) {
}

当没有指定泛型时,默认类型为Object类型。

  • 避免了类型强转的麻烦。
  • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。

泛型没有继承多态关系 Collection<Object> list = new ArrayList<String>();这种是错误的。

在Java的泛型中可以指定一个泛型的上限下限

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义只能接收该类型及其子类
  • 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
    public static void getElement1(Collection<? extends Number> coll){}

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义只能接收该类型及其父类型
  • 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
    public static void getElement2(Collection<? super Number> coll){}

习惯上选择以下字母代表某种类型:

泛型类型不确定,可以通过通配符<?>表示。

  1. T 意味某种类型。
  2. E 意味 链表、数组里的元素,如List list 表示 list 里的元素。
  3. K意味map(k,v) 里的键值 Key
  4. V 意味 返回或映射的值。

然而,泛型的运用要受到如下限制 :

  • 不能使用基本类型的类型参数,可以使用其包装类型代替。
  • 静态成员无法使用类型参数。
  • 不能使用泛型类异常
  • 不能实例化泛型对象或数组,如:
    T t = new T(); T[] a=new T5;
  • 不能使用泛型数组。

Collections类:

Collections是为集合框架提供服务的工具类,里面的所有方法都是静态方法,功能包括对集合排序、折半查找、拷贝、随机、交换、同步等。

java.utils.Collections用来对集合进行操作。部分方法如下:

  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • public static void shuffle(List<?> list):打乱集合顺序。
  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
  • public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

Comparator比较器

Collections中sort重载的规则是怎么来的呢
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现java.lang.Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现java.util.Comparator接口即可。

想要字符串按照第一个字符降序排列,那么这样就要修改String的源代码,这是不可能的了,那么这个时候我们可以使用public static <T> void sort(List<T> list,Comparator<? super T> )方法灵活的完成,

Collections.reverseOrder(); : 将比较器反转,快速实现倒序。

也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。之后可以使用lambda表达式简化。

Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o2.indexOf(1)-o1.indexOf(1);
    }
});
Collections.sort(list, (o1, o2) -> o2.indexOf(1)-o1.indexOf(1));

Comparable 是排序接口

若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过Collections.sort(或 Arrays.sort)(C调用A调用Timsort)来进行排序。

此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。

Collections.sort(list);

重写compareTo()方法。

那么我们采用的public static <T> void sort(List<T> list)这个方法完成的排序,实际上要求了被排序的类型需要实现Comparable接口完成比较的功能,在String类型上如下:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {}

String类实现了这个接口,并完成了比较规则的定义,无法改变。

public static <T> void sort(List<T> list,Comparator<? super T> )方法灵活的完成,这个里面就涉及到了Comparator这个接口,位于java.util包下,排序是comparator能实现的功能之一:

  • public int compare(String o1, String o2):比较其两个参数的顺序。

    两个对象比较的结果有三种:大于,等于,小于。
    如果要按照升序排序,
    则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)
    如果要按照降序排序
    则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)

简述Comparable和Comparator两个接口的区别。

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。


Collectionの具体实现类


ArrayList:动态数组

使用泛型:实例化后全部是统一的类型,且泛型只能是引用类型。

ArrayList<String> list = new ArrayList<>(); //从JDK1.7开始,右侧尖括号内可以不写内容,但得有<>。

从JDK 1.5开始支持自动装箱、自动拆箱。即只需要在< E >中使用包装,输入返回都可以直接用基本类型,详见包装类。

ArrayList的常用方法:

ArrayList集合重写了toString。

public boolean add(E e);
public E get(int index); //从0开始,返回泛型E的对应值
public E remove(int index);//删除并返回该索引的元素
public int size();//无参,返回集合的长度

add的返回值对于ArrayList来说一定是true的,所以没什么用,但对于其他集合,add方法不一定成功。

Example:

创建一个Student类的ArrayList:

ArrayList<Student> info = new ArrayList<>();
info.add(new Student("zly", 10));
info.add(new Student("lvlvsun", 15));
info.add(new Student("leaky", 20));
info.add(new Student("Relu", 30));
for (int i = 0; i < info.size(); i++) {
    System.out.println(info.get(i).getName());
    System.out.println(info.get(i).getAge());

创建20个数,取其中偶数:

public static void main(String[] args) {
    int[] list = new int[20];
    Random r = new Random();
    for (int i = 0; i < 20; i++) {
        list[i] = r.nextInt(100) + 1;
    }
    System.out.println(getEven(list));

}

public static ArrayList<Integer> getEven(int[] list) {
    ArrayList<Integer> listA = new ArrayList<>();
    for (int i = 0; i < list.length; i++) {
        if (list[i] % 2 == 0) {
            listA.add(list[i]);
        }
    }
    return listA;
}

List的子类

List接口:

java.util.List是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合。在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

元素有索引,equals方法确定是否为重复元素,存储元素和取出元素的顺序是一致的(存储123 取出123)

常用方法:

继承了Collection接口中的全部方法,还增加了一些根据元素索引来操作集合的特有方法,如下:

public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。

public E get(int index):返回集合中指定位置的元素。

public E remove(int index) : 移除元素, 返回的是被移除的元素。

public E set(int index, E element) :替换元素,返回值为更新前的元素

// 跟size() 方法一起用  来 遍历的
for(int i = 0;i<list.size();i++){
    System.out.println(list.get(i));
}
//使用迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
    String s = it.next();
    System.out.println(s);
}
//还可以使用增强for
for (String string : list) {
    System.out.println(string);
}

ArrayList集合

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。

LinkedList集合

java.util.LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。

在这里插入图片描述

LinkedList方法,了解即可
  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。
  • public void push(E e):将元素推入此列表所表示的堆栈。
  • public boolean isEmpty():如果列表不包含元素,则返回true。

BitSet

独立的数据储存结构

继承状态implements Cloneable, java.io.Serializable

储存一位判断符号,可以大量节省空间。

插入此列表的开头。

  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。
  • public void push(E e):将元素推入此列表所表示的堆栈。
  • public boolean isEmpty():如果列表不包含元素,则返回true。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值