java遍历范型list_黑马程序员--Java基础学习笔记【集合-List、泛型】

集合框架 Collection  java.util(interface)

集合 只能存储引用类型,存储对象,不存储基本类型,长度可变

数组 存储基本类型,存储对象,长度固定

集合中存储的都是引用类型的元素,那么引用类型变量实际上存储的是对象的“地址”,所以实际上集合只存储了元素对象在堆中的地址,而并不是将对象本身存入了集合中。

Collection接口

是层次结构中的根接口,定义了集合相关的操作方法。

其有两个子接口:List(可重复集)和Set(不可重复集)

元素是否重复,取决于元素的equals() 比较的结果

成员方法:

boolean add(E e)//添加元素

boolean remove(E e) //移除第一次出现的指定元素

void clear() //清空集合

boolean contains(Object o)//判断是否包含指定对象

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

int size()//返回集合的大小(容量),即集合中存储元素的个数

boolean addAll(Collection c) //添加指定集合中的所有元素

boolean removeAll(Collection c) //移除指定集合中包含的所有元素

boolean containsAll(Collection c) //判断是否包含指定集合的所有元素

boolean retainAll(Collection c) //保留与指定集合中相同的元素(获取交集)

Object[] toArray()//集合 --> 数组,可以实现集合的遍历

Iterator iterator()//获取迭代器,集合专用的遍历方式

*迭代器迭代结合,泛型跟随集合

Iterator迭代器

集合专用遍历方式,做集合中元素的获取

集合顶层接口Collection中,定义了一个抽象方法Iterator iterator(),返回值是接口类型,返回的是该接口的实现类对象。

迭代器接口的实现类是集合容器的内部类,Collection下面所有的实现类,都会重写该方法。比如 ArrayList 实现 List 接口,而 List 继承自Collection。

迭代器类的成员方法:

boolean hasNext() //判断集合中是否还有下一个元素

next() //获取迭代的下一个元素

void remove() //移除本次迭代后迭代器返回的最后一个元素

迭代器的删除方法是在原集合中删除元素ConcurrentModificationException

在使用迭代器遍历集合时,不能通过集合的remove() 方法删除集合元素,否则会抛出并发更改异常,可以通过迭代器自身提供的remove() 方法删除通过next() 迭代出的元素。

在调用remove() 方法前必须通过迭代器的next() 方法迭代过元素,那么删除的就是这个元素。并且不能再次调用remove() 方法,除非再次调用next() 后方可再次调用。

使用迭代器接口的两种方式,一般使用 while 循环

Iteratoriterator=collection.iterator();

//调用迭代器接口方法判断集合中有没有下一个元素

while(iterator.hasNext()) {

//调用迭代器接口方法获取出集合中的元素

Objectobject=iterator.next();

System.out.println(object);

}

for(Iteratoriterator=collection.iterator();iterator.hasNext();){

Objectobject=iterator.next();

System.out.println(object);

}

增强型for循环

since JDK1.5,只用于遍历集合或数组,也称新循环

格式:

for(元素类型 变量名 : 集合或数组) {

循环体

}

好处:减少代码量,方便做遍历;弊端:不能改动数组或集合中的元素

增强for循环并非新的语法,而是在编译过程中,编译器会将新循环转换为迭代器模式。所以新循环本质上是迭代器。

遍历集合的 3 种方式:迭代器,增强 for 循环,普通for 循环(size() + get())

List接口 继承 Collection 接口

特点:有序集合,存取有序,有索引,允许重复

成员方法

void add(int index, E element) //向指定索引处添加元素

E remove(int index) //移除指定索引处的元素并返回该元素

E get(int index) //获取指定索引上的元素

E set(int index, E element) //替换指定索引上的元素并返回之前的元素

ListIterator listIterator() //获取迭代器

int lastIndexOf(Object o) //返回指定元素出现的最后一个位置的索引

List subList(int fromIndex, inttoIndex) //获取子List

--------------------------------------------------------------------

importjava.util.ArrayList;

importjava.util.List;

/*

*证明subList获取的List与原List占用相同的存储空间,对子List的操作会影响原List

*/

public classSubListDemo {

public static void main(String[] args) {

List list = newArrayList<>();

for (int i = 0; i < 10; i++) {

list.add(i);

}

System.out.println("list " +list);

// list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

List subList =list.subList(3, 8);

System.out.println("subList " +subList);

// sublist [3, 4, 5, 6, 7]

// subList获得的List和原List占有相同的数据空间

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

subList.set(i, subList.get(i) * 10);

}

System.out.println("changedsubList" + subList);

// changedsublist [30, 40, 50, 60, 70]

System.out.println("unchangedlist" + list);

// unchangedlist [0, 1, 2, 30, 40, 50,60, 70, 8, 9]

list.subList(3, 8).clear(); //可以用于删除连续元素

System.out.println(list);

// [0, 1, 2, 8, 9]

}

}

ListIterator列表迭代器

允许按任一方向遍历列表,迭代期间可以修改列表

void add(E e)

booleanhasNext() //正向遍历

boolean hasPrevious() //逆向遍历

E next() //返回列表中的下一个元素

int nextIndex() //返回返回下一个索引

E previous() //返回列表中的前一个元素

int previousIndex() //返回前一个索引

void remove() //移除本次迭代后迭代器返回的最后一个元素

void set(E e) //替换此次迭代后迭代器返回的最后一个元素

对 List 集合进行正向遍历和逆向遍历

Listlist=newArrayList<>();

list.add("www");

list.add("itcast.");

list.add("cn");

//调用集合方法,获取ListIterator接口的实现类对象

ListIteratoriterator=list.listIterator();

while(iterator.hasNext()) {

Objectobject= (Object)iterator.next();

if("www".equals(object)) {

//调用迭代器的方法

//添加元素到迭代到元素的下一个位置

//            iterator.add("0807Java");//添加和修改不能在同一次迭代中

//修改迭代到的元素

iterator.set("www.");

}

}

//迭代器指针到了最后,不能再次获取,出现没有元素被取出异常

//逆向遍历逆向遍历之前要先做一次正向遍历

while(iterator.hasPrevious()) {

Objectobject= (Object)iterator.previous();

System.out.print(object+" ");// cn itcast. www.

}

泛型机制Generic since JDK5

泛型在集合中的应用

泛型的本质是参数化类型。在类、接口和方法的定义过程中,所操作的数据类型被传入的参数指定,强制集合必须存储指定的数据类型,保证程序的安全性。

Java泛型机制广泛的应用在集合框架中,所有的集合类型都带有泛型参数,这样在创建集合时可以指定放入集合中元素的类型。Java编译器可以据此进行类型检查,这样可以减少代码在运行时出现错误的可能性。

集合类变量名= new集合类();

好处:减少代码量,避免类型强制转换,安全问题由运行时期提前到了编译时期。

Java中的泛型是伪泛型,只在编译时期有效,编译后的class文件中没有泛型,编译手段。

ArrayList类的定义中,中的E为泛型参数(理解为变量名,相当于定义了一个变量,负责接收数据类型),在创建对象时可以将类型作为参数传递,此时,类定义所有的E将被替换成传入的参数。

*注意:集合存储八种基本类型,泛型必须写包装类;迭代器迭代结合,泛型跟随集合

泛型类、泛型方法

packagecn.itcast;

/*

*自定义泛型类

*自己写的类上,加上泛型

*

*定义成员变量,也是泛型

*

* E变量,等待建立此类对象的时候,由调用者指定他的数据类型

*/

classGenericClass {

privateEe;

/*

*泛型方法

*方法参数上,使用了一个和类上一样的泛型

*创建类的对象的时候,直接指定数据类型

*

*方法上泛型需要单独的定义,定义在方法的声明上

*创建类的对象同时,不能指定方法上泛型,调用者调用方法时直接指定

*

*静态方法参数上的泛型,不能和类上的泛型一样

*原因:静态不能直接调用非静态

*/

publicvoidshow(Ee) {

System.out.println(e);

}

publicvoidfunction(Ww){

System.out.println(w);

}

publicstaticvoidmethod(Cc){

System.out.println(c);

}

publicE getE() {

returne;

}

publicvoidsetE(Ee) {

this.e=e;

}

}

publicclassGenericDefine {

publicstaticvoidmain(String[]args) {

GenericClassgenericClass=newGenericClass();

genericClass.setE(123);

Integerinteger=genericClass.getE();

System.out.println(integer);

GenericClassgenericClass2=newGenericClass();

genericClass2.setE("abc");

Stringstring=genericClass2.getE();

System.out.println(string+ 1);

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

genericClass2.show("传智播客");

}

}

泛型接口

packagecn.itcast;

/*

*泛型接口

*接口上定义泛型,接口中方法全抽象,实现类

*在使用上两种使用方式:

*实现类实现接口,不理会泛型

*实现类实现接口,同时也实现接口上的泛型

*/

interfaceInter {

publicabstractvoidshow(Tt);

}

//定义接口的实现类,实现接口,不理会接口上的泛型

//泛型的指定,实现类没有做,让调用者来指定数据类型

classInterImplimplementsInter {

@Override

publicvoidshow(Tt) {

System.out.println(t);

}

}

//定义接口的实现类,实现接口的同时,也实现泛型--不灵活

classInterImpl2implementsInter{

@Override

publicvoidshow(Stringt) {

System.out.println(t);

}

}

publicclassGenericInterfaceDemo {

publicstaticvoidmain(String[]args) {

Interin=newInterImpl();

in.show(123);

Interin2=newInterImpl();

in2.show("itcast");

}

}

泛型的限定:泛型通配符>

? extends E(向下限定,E及其子类)? super E(向上限定,E及其父类)

线性表

List接口是Collection的子接口,用于定义线性表数据结构,可以将List理解为存放对象的数组,只不过其元素个数可以动态的增加或减少。

List接口的两个常用实现类为ArrayList和LinkedList,分别用动态数组和链表的方式实现了List接口。

List三个子类的特点

共同特点:有序,索引,重复。

ArrayList和LinkedList在性能上有一定的差别。

ArrayList更适合于随机访问,而LinkedList更适合于插入和删除。

ArrayList底层数据结构是可变数组,元素查询速度快,增删慢

线程不安全,不同步,运行速度快

默认容量10,增长率50%

LinkedList底层数据结构是双向链表,元素查询速度慢,增删快

线程不安全,不同步,运行速度快

存储和迭代器代码,和ArrayList完全一样

Vector底层数据结构是可变数组,元素查询速度快,增删慢

线程安全,同步,运行速度慢

默认容量10,增长率100%

Vector类特有方法:

void addElement(E obj) //将指定的组件添加到向量的末尾,容量+1

E elementAt(int index) //返回指定索引处的组件

Enumeration elements() //返回此向量的组件的枚举

LinkedList类特有方法:

void addFirst(E e)       voidaddLast(E e);

E getFirst()         EgetLast()

E removeFirst()      EremoveLast()

去除集合中存储的重复元素

package cn.itcast;

importjava.util.ArrayList;

importjava.util.Iterator;

/*

*去除集合中字符串的重复值--去除数组中重复元素

*去除集合中自定义对象的重复值(需要重写自定义对象的equals()方法)

* ArrayList集合实现,List允许重复

*(String类重写了equals()方法,建立了自己的比较方式)

*如果原集合中元素没有出现在新集合中,将该元素存储到新集合中

*遍历完毕,新集合保存的就是去掉重复后的元素

*将原集合的引用指向新集合

*/

public classArrayListTest {

public static void main(String[] args) {

ArrayList list = new ArrayList();

list.add("www");

list.add(".itcast");

list.add(".cn");

list.add("www");

list.add(".itheima");

list.add(".com");

list = removeSame(list);

System.out.println(list); // [www, .itcast, .cn, .itheima,.com]

}

//返回的是去重复之后的新集合

public static ArrayListremoveSame(ArrayList arrayList) {

//创建新集合,保存去重复之后的元素

ArrayList newList = newArrayList();

//迭代原集合

Iterator iterator = arrayList.iterator();

while (iterator.hasNext()) {

//接收迭代元素的结果

String string = iterator.next();

//判断新集合中是否包含该元素,没有则添加进去

if (!newList.contains(string)) {

newList.add(string);

}

}

return newList;

}

}

LinkedList模拟栈数据结构的集合

packagecn.itcast;

importjava.util.LinkedList;

/*

* LinkedList集合,模拟数据结构栈

*

*将LinkedList集合中的功能封装起来,调用者不直接面对集合,只能从外部调用

*表现为先添加的元素后被取出,存储和取出的顺序是相反的

*/

publicclassLinkedListTest {

publicstaticvoidmain(String[]args) {

LinkedListToollist=newLinkedListTool();

list.add(0);

list.add(1);

list.add(2);

list.add(3);

//当列表不为空时,删除元素并返回

while(!list.isEmpty()) {

System.out.println(list.remove());

}

}

}

//自定义功能,封装LinkedList类功能

classLinkedListTool {

//定义成员变量

privateLinkedListlist;

//构造方法用于新建对象

publicLinkedListTool() {

list=newLinkedList();

}

//添加元素到列表结尾

publicvoidadd(Objectobject) {

list.add(object);

}

//判断列表是否为空

publicbooleanisEmpty() {

returnlist.isEmpty();

}

//从列表结尾删除元素并返回

publicObject remove() {

returnlist.removeLast();

}

}

List集合< == >数组

List转换为数组(集合转成数组,带有泛型)

Object[] toArray()

T[] toArray(T[] a)

Liststrings=newArrayList<>();

strings.add("www");

strings.add(".itcast");

strings.add("cn");

String[]str=strings.toArray(newString[strings.size()]);

//传入一个指定类型的数组,该数组的元素类型应与集合的元素类型一致。

//返回值则是转换后的数组,该数组会保存集合中所有的元素

for(inti= 0;i

System.out.print(str[i] +" ");

}

数组转换为List

Arrays类中提供了一个静态方法asList,使用该方法我们可以将一个数组转换为对应的List集合。其方法定义为:static List asList

注意:返回的List的集合元素类型由传入的数组的元素类型决定;返回的集合不能对其增删元素,否则会抛出异常,并且对集合的元素进行修改会影响数组对应的元素。

String[]strArr= {"www",".itcast",".cn"};

Listlist =Arrays.asList(strArr); // fixed-size list

System.out.println(list);// [www, .itcast, .cn]

//当前集合list的实际类型为java.util.Array$ArrayList

//而不是List接口的实现类java.util.ArrayList,所以不支持对其添加或删除元素

// list.add("IT"); //会抛出UnsupportedOperationException

System.out.println(list.getClass().getName());

list.set(0,"3w");//可以修改元素

//对集合元素的修改会影响原数组

System.out.print("String[] ");

for(Stringstring:strArr) {

System.out.print(string+" ");

}

System.out.println();

//如果想要添加元素,可以用如下方式:

Listlist2=newArrayList<>();

list2.addAll(Arrays.asList(strArr));

System.out.println(list2);// [3w, .itcast, .cn]

list2.add("0807JavaSE");

System.out.println(list2);// [3w, .itcast, .cn, 0807JavaSE]

可变参数since JDK5

如果定义方法的时候,参数类型明确但个数不明确,可使用可变参数

格式:修饰符返回值类型方法名(数据类型...变量名) {}

可变参数方法传递,传递实际参数,数量没有限制

注意:一个方法中只能写1个可变参数,如果有多个参数可变参数只能放在最后

packagecn.itcast.arguments;

publicclassVarArgumentsDemo {

publicstaticvoidmain(String[]args) {

intsum= getSum(0, 1,2, 3, 4, 5);

System.out.println(sum);

}

publicstaticintgetSum(int...is){

intsum= 0;

//传递参数的个数,就是数组的长度

//如果不传递任何参数,可变参数的数组的长度就是0

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

//         sum+= is[i];

//     }

for(inti:is) {

sum+=i;

}

returnsum;

}

}

l获取10个1-20之间的随机数,要求不能重复

package cn.itcast.test;

importjava.util.ArrayList;

import java.util.List;

importjava.util.Random;

/*

*获取10个1-20之间的随机数,要求不能重复

*/

public class ListTest {

public static void main(String[] args) {

Random r = new Random();

List list = new ArrayList();

while (true) {

//获取随机数

int num = r.nextInt(20) + 1;

//判断随机数如果不在集合中,就存储到集合

if (!list.contains(num)) {

list.add(num);

//判断集合容量为10就退出循环

if (list.size() == 10) {

break;

}

}

}

for (Integer integer : list) {

System.out.println(integer);

}

}

}

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

package cn.itcast.test;

importjava.util.ArrayList;

import java.util.List;

importjava.util.Scanner;

/*

*键盘录入多个数据,以0结束

*在控制台输出最大值:

*利用数组,将集合转成数组

*     1.升序排序,获取最后一个元素

*     2.获取数组中的最大值

*

*/

public classListScannerTest {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

List list = new ArrayList();

while (true) {

int num = sc.nextInt();

if (num == 0) {

break;

}

//数据存储到集合中

list.add(num);

}

sc.close();

//     System.out.println(list);

//将集合转成数组

Integer[] integers = list.toArray(new Integer[list.size()]);

//选择排序

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

for (int j = i + 1; j < integers.length; j++) {

if (integers[i] > integers[j]) {

int temp = integers[i];

integers[i] = integers[j];

integers[j] = temp;

}

}

}

//输出数组中的最后一个索引

System.out.println(integers[integers.length - 1]);

//求数组最值思想

//     int max = list.get(0);

//     for (Integer integer : integers) {

//         if (integer > max)

//            max = integer;

//     }

//     System.out.println(max);

}

}

List排序

Collections.sort()方法实现排序

Collections是集合的工具类,提供很多便于操作集合的方法。

void sort(Listlist) //该方法的作用是对给定的集合元素进行自然排序

你可能感兴趣的:(java遍历范型list)