11、集合(1)

1、集合

介绍:集合,集合是java中提供的一种容器,可以用来存储多个数据。出现意义:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。Java中的集合: JDK为我们提供了一套完整的容器类库,这些容器可以用于存储各种类型的对象,并且长度都是可变的,我们把这些类统称为集合类,它们都位于java.util包中。

☆集合和数组区别:数组的长度是固定的。集合的长度是可变的。集合中存储的元素必须是引用类型数据。

Collection概念:Collection是所有单列集合的直接或间接接口,其指定了所有集合应该具备的功能。集合体系如图:在这里插入图片描述
☆List总结

  1. 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ];
  2. 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ];
  3. 所有的List中可以有null元素,例如[ tom,null,1 ];
  4. 基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。

☆Set总结
6. Set实现的基础是Map(HashMap);
7. Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

Collection通用方法
boolean add(E e) //添加元素
boolean remove(Object o) //删除元素
void clear() //清空集合
boolean contains(Object o) //判断是否包含某元素
boolean isEmpty() //判断是否为空
int size() //获取集合长度

增强for循环:增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。增强for循环用来迭代集合或数组。
☆格式:for(元素的数据类型 变量 : Collection集合or数组){}
☆注意:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过角标操作。

迭代器:集合用来持有数据,一定会设计出对数据的增、删、改、查四个常用方法,而查是集合中最常用的功能。Collection接口继承了Iterable接口,具备了可迭代功能iterator方法,该方法用于迭代集合。所以,所有单列集合由于是Collection的直接或间接实现类,均具有该方法。而增强for循环让迭代器循环访问的方式更加简便。
☆区别for循环:1、如果在for循环的过程中调用集合的remove()方法,就会导致并发修改异常 。因为循环过程中list.size()长度变小导致了错误。如果想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法。2、在ArrayList里,for循环较快;在LinkedList里,使用iterator较快。

迭代常规步骤:1、通过集合获取这个集合的迭代器。 2、结合使用迭代器的hashNext与next完成集合迭代。

ArryList<String> list = new ArryList <String>();
list.add("i love java");
list.add("i like java");
Iterator<String> iterator = list.iterator();//返回迭代器
while (iterator.hasNext()) {
String string = iterator.next();
System.out.println(string);}

迭代集合元素图解在这里插入图片描述

public class Demo {
	public static void main(String[] args) {
	Collection  c  = new ArrayList();
	c.add("111");
	c.add("追");
	c.add(111);
	Iterator iterator = c.iterator();  // Iterator 接口  指向 子类对象.
	while(iterator.hasNext()){// 2.调用迭代器的方法,获取集合中的元素.
	Object next = iterator.next();
	System.out.println(next);}
	}
}

说明:遍历之前,有一个指针指向初始位置,第一个元素的前面, hasNext,判断是否在指针后面有元素,有返回true ,没有返回false 。如果有 , 就可以通过 next() 获取下一个元素了。

public class Demo {
	public static void main(String[] args) {
	Person s1 = new Person("顾慎为" , 20);
	Person s2 = new Person("独步王" , 59);
	Collection<Person> c = new ArrayList<>();
	c.add(s1);
	c.add(s2);
	System.out.println(c);
	Iterator<Person> it  = c.iterator();//获取迭代器
	while (it.hasNext()) {
	Person p  = it.next();
	if(p.getAge() <59){
	//c.remove(p);ConcurrentModificationException 并发修改异常 .
	it.remove(); // 移除当前迭代的元素. (迭代器移除方法可以避免并发修改异常)
	System.out.println(p.getName() +" --- "+ p.getAge());
	}
	}
}
class Person {
	String name;
	int age;
	public Person(String n,int a){
	this.name=n;
	this.age=a;
	}
	public String getName(){
	return name;
	}
	public int getAge(){
	return age;
	}
}

并发修改异常:迭代过程中并发修改异常的原因为迭代器中”记忆”的集合长度与集合中实际长度不同,而导致出现索引与实际元素不符甚至无限循环的情况发生。所以在使用Iterator时,避免类似操作,for循环底层为迭代器实现,所以也需要避免类似操作。有些迭代器避免了这样的问题,如ListIterator,但该类并不通用也不常用,实际开发中很少使用,只需要简单了解。

2、泛型

概述:泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数传递。泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。泛型的定义:定义泛型可以在类中预支地使用未知的类型。泛型的使用:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。常见应用:泛型类、泛型方法、泛型接口

含有泛型的类
定义格式:修饰符 class 类名<代表泛型的变量> { }

//例如,API中的ArrayList集合
class ArrayList<E>{public boolean add(E e){ };public E get(int index){  }}

使用格式:创建对象时,确定泛型的类型。
ArrayList list = new ArrayList<>();

含有泛型的方法
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }

//例如,API中的ArrayList集合中的方法:
public <T> T[] toArray(T[] a){  }//该方法,用来把集合元素存储到指定数据类型的数组中,返回已存储集合元素的数组

使用格式:调用方法时,确定泛型的类型。
ArrayList list = new ArrayList<>();
String[] arr = new String[100];
String[] result = list.toArray(arr);

含有泛型的接口
定义格式:修饰符 interface接口名<代表泛型的变量> { }

//例如,API中的Iterator迭代器接口
public interface Iterator<E> {public abstract E next();}

使用格式:
1、定义类时确定泛型的类型
public final class Scanner implements Iterator { public String next(){ }}
2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型
Collection list = new ArrayList<>();
Iterator it = list.iterator();//此时,变量E的值就是String类型。

泛型通配符:在JDK1.5出现前,使用Object代表任意类型,但在使用时,涉及到了强转的麻烦。泛型替代了Object来代表任意类型。泛型在编译时会擦除:泛型仅用来在编译期限制、方便程序员的操作,实际上真正编译后的.class中是没有泛型的,其中仍然使用的为Obejct类,通过类似多态的方式完成任意某个类型的指定。当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
☆泛型优点:提高了程序的安全性;将运行期遇到的问题转移到了编译期;省去了类型强转的麻烦。

/*
泛型通配符?,代表任意的数据类型
使用:调用方法时可以给予任意类型。参照Arraylist的构造方法
public ArrayList(Collection<? extends E> c)
? extends E代表只要是E类型的子类即可
? super E代表只要是E类型的父类即可
*/
public class Demo {
	public static void main(String[] args) { 
	ArrayList<String> listB = new ArrayList<>();
	listB.add("Trump");
	//创建集合对象A时,给于另外一个集合对象B作为参数,则创建好的集合A中包含了集合B中的元素
	ArrayList<Object> listA = new ArrayList<Object>(listB);
	listA.add("Obama");
	System.out.println(listA);
	}
}

猜你喜欢

转载自blog.csdn.net/ao__ao/article/details/83042590
今日推荐