黑马程序员 Java基础 集合

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一 引入

对象数组不能适应变化的需求,因为数组的长度是固定的,这个时候,Java就提供了集合类供我们使用。

数组和集合的区别?

 * A:长度区别

 * 数组的长度固定

 * 集合长度可变

 * B:内容不同

 * 数组存储的是同一种类型的元素

 * 而集合可以存储不同类型的元素

 * C:元素的数据类型问题

 * 数组可以存储基本数据类型,也可以存储引用数据类型

 * 集合只能存储引用类型

 

二 Collection

 1 Collection的功能概述:

 * 1:添加功能

 * boolean add(Object obj):添加一个元素

 * boolean addAll(Collection c):添加一个集合的元素

 * 2:删除功能

 * void clear():移除所有元素

 * boolean remove(Object o):移除一个元素

 * boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)

 * 3:判断功能

 * boolean contains(Object o):判断集合中是否包含指定的元素

 * boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有)

 * boolean isEmpty():判断集合是否为空

 * 4:获取功能

 * Iterator<E> iterator()(重点)

 * 5:长度功能

 * int size():元素的个数

 * 面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?

 * 6:交集功能

 * boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?

 * 7:把集合转换为数组

 * Object[] toArray() 

 

2集合的遍历

代码如下:

Iterator it = c.iterator();

while (it.hasNext()) {

// System.out.println(it.next());

String s = (String) it.next();

System.out.println(s);

}
 

注意:

1 for循环改写

for(Iterator it = c.iterator();it.hasNext();  ){

Student s = (Student) it.next();

System.out.println(s.getName() + "---" + s.getAge());

}

可以使itfor循环里,跳出循环体后,it便可以被垃圾回收了,更好

 

2 it.next() 慎用

如果上面的代码写成

for(Iterator it = c.iterator();it.hasNext();  ){

System.out.println(it.next().getName() + "---" + it.next().getAge());

}

看起来似乎没问题,但其实出错了。

因为it.next()会自动指向下一个,所以it.next().getName()it.next().getAge()得到的不是同一个学生的姓名和年龄。

 

List

1 List集合的特有功能

因为List是有序的,所以可以指定位置

 * A:添加功能

 *  void add(int index,Object element):在指定位置添加元素

 * B:获取功能

 *  Object get(int index):获取指定位置的元素

 * C:列表迭代器

 *  ListIterator listIterator()List集合特有的迭代器

 * D:删除功能

 *  Object remove(int index):根据索引删除元素,返回被删除的元素

 * E:修改功能

 *  Object set(int index,Object element):根据索引修改元素,返回被修饰的元素

 

特有的遍历方式

for (int x = 0; x < list.size(); x++) {

Student s = (Student) list.get(x);

System.out.println(s.getName() + "---" + s.getAge());

}


因为Listget()方法,可以获取特定位置的元素,所以可以这样遍历

 

3 listIterator()方法介绍

特有功能:

 *  Object previous():获取上一个元素

 *  boolean hasPrevious():判断是否有元素

 

逆向遍历代码:

ListIterator lit = list.listIterator(); 

while (lit.hasPrevious()) {

String s = (String) lit.previous();

System.out.println(s);

}

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


而这样子是不会输出任何结果的。因为一开始的时候,lit是指向该对象的第一个的,所以lit.hasPrevious()false

ListIterator可以实现逆向遍历,但是必须先正向遍历,到达末尾,才能逆向遍历。所以一般无意义,不使用。

 

listIterator()的其他使用

问题描述:判断一个集合里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素代码实现:

// Iterator it = list.iterator();

// while (it.hasNext()) {

// String s = (String) it.next();

// if ("world".equals(s)) {

// list.add("javaee");

// }

// }


这段代码看似没问题,却会报错如下:

 ConcurrentModificationException 当方法检测到对象的并发修改,不允许这种修改

 

解决办法如下:

方式1:迭代器

// Iterator迭代器没有添加功能,但其子接口ListIterator有

ListIterator lit = list.listIterator();

while(lit.hasNext()){

String s = (String)lit.next();

if("world".equals(s)){

lit.add("javaee");

}

}


直接在lit(迭代器)上增加(或进行其他修改)

 

方式2get()

for (int x = 0; x < list.size(); x++) {

String s = (String) list.get(x);

if ("world".equals(s)) {

list.add("javaee");

}

}


因为遍历方式有两种,而get()方法不涉及并发修改,所以可以直接在集合上增加(或进行其他修改)

 

4 list的子类特点(重点)

    ArrayList:

底层数据结构是数组,查询快,增删慢。

线程不安全,效率高。

Vector:

底层数据结构是数组,查询快,增删慢。

线程安全,效率低。

LinkedList:

底层数据结构是链表,查询慢,增删快。

线程不安全,效率高。

List有三个儿子,我们到底使用谁呢?

要安全吗?

要:Vector(即使要安全,也不用这个了,后面有替代的)

不要:ArrayList或者LinkedList

查询多:ArrayList

增删多:LinkedList

如果你什么都不懂,就用ArrayList

 

四 List子类

1 Vector

 特有功能:

 * 1:添加功能

 *  public void addElement(Object obj) -- add()

 * 2:获取功能

 *  public Object elementAt(int index) --  get()

 *  public Enumeration elements() -- Iterator iterator()

 *  boolean hasMoreElements() hasNext()

 *  Object nextElement() next()

 

因为它出现的早,所以有其特有的函数。但是功能是类似的,右边的是对应的在Collection中的函数名称(实现功能相同)

 

2 LinkedList

特有功能:

 *  1: 添加功能

 *  public void addFirst(Object e)

 *  public void addLast(Object e)

 *  2: 获取功能

 *  public Object getFirst()

 *  public Obejct getLast()

 *  3: 删除功能

 *  public Object removeFirst()

 *  public Object removeLast()

 

因为LinkedList类是基于链表的存储结构,所以可以比较容易的对首尾进行修改,所以如上所示

 

3易混点:

array.add(10);

这句话没有错。集合只能作用于对象,但是jdk5会把这句话转成:

array.add(new Integer(100));

 

五 案例

1 ArrayList去除集合中字符串的重复值(字符串的内容相同)

for(int i = 0; i < array.size(); i++){

String s = array.get(i);

array.remove(i);

 

if(!array.contains(s)){

array.add(i, s);

i++;

}

i--;

}


 

去除集合中自定义对象的重复值(对象的成员变量值都相同)

直接用上面的代码会出错。因为contains()方法的底层依赖的是equals()方法。

所以要按照我们自己的需求,重写equals()

 

集合的嵌套遍历

比如ArrayList<ArrayList<Student>>,可以代表一个班里有很多学生(ArrayList<Student>),有很多班(ArrayList<ArrayList<Student>>)。像数组中的二维数组。

如果多层嵌套,就像是多维数组。

ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>();

 

ArrayList<Student> firstArrayList = new ArrayList<Student>();

firstArrayList.add(new Student("唐僧", 30));

firstArrayList.add(new Student("孙悟空", 29));

firstArrayList.add(new Student("猪八戒", 28));

firstArrayList.add(new Student("沙僧", 27));

firstArrayList.add(new Student("白龙马", 26));

 

bigArrayList.add(firstArrayList);

 

ArrayList<Student> secondArrayList = new ArrayList<Student>();

secondArrayList.add(new Student("诸葛亮", 30));

secondArrayList.add(new Student("司马懿", 28));

secondArrayList.add(new Student("周瑜", 26));

bigArrayList.add(secondArrayList);

 

for(ArrayList<String> big: bigArrayList){

for(Student s: big){

System.out.println(s.getName() + "---" + s.getAge());

}

}



增强for循环

 

 

键盘录入多个数据,以0结束,并在控制台输出最大值

/*

 * 键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值

 * 

 * 分析:

 *  D:把集合转成数组

 *  E:对数组排序

 *  F:获取该数组中的最大索引的值

 */

public class ArrayListDemo {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

 

ArrayList<Integer> array = new ArrayList<Integer>();

 

while (true) {

System.out.println("请输入数据:");

int number = sc.nextInt();

if (number != 0) {

array.add(number);

} else {

break;

}

}

 

Integer[] i = new Integer[array.size()];

array.toArray(i);

 

Arrays.sort(i);

 

System.out.println("数组是:" + arrayToString(i) + "最大值是:"

+ i[i.length - 1]);

}

 

public static String arrayToString(Integer[] i) {

StringBuilder sb = new StringBuilder();

 

sb.append("[");

for (int x = 0; x < i.length; x++) {

if (x == i.length - 1) {

sb.append(i[x]);

} else {

sb.append(i[x]).append(", ");

}

}

sb.append("]");

 

return sb.toString();

}

}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值