继续讲ArrayList集合:ArrayList集合是List集合的一个常用类,ArrayList集合是线程不安全的,但是效率高,所以没有要求的情况下可以默认使用ArrayList集合存储对象。存储自定义变量并遍历的方法:
(1)调用iterator迭代器
(2)size()和get(int index)普通for循环。
如果集合中存储的是对象,那么以上两种方法同样适合,下面是对象数组Student的遍历例子:
import java.util.ArrayList;
import java.util.Iterator;
public class Test2 {
public static void main(String[] args) {
//创建集合对象
ArrayList<Student> s = new ArrayList<Student>() ;
Student s1 = new Student("aloha", 22) ;
Student s2 = new Student("alohaa",23) ;
Student s3 = new Student("alohaaa",24) ;
s.add(s1) ;
s.add(s2) ;
s.add(s3) ;
//迭代器遍历
Iterator<Student> it = s.iterator();
while(it.hasNext()) {
Student stu = it.next() ;
System.out.println(stu.getName() + "---" + stu.getAge());
}
System.out.println("-----------------------------");
//size()和set(int index)遍历
for(int x = 0 ;x <s.size() ;x++) {
Student stu = s.get(x) ;
System.out.println(stu.getName() + "---" + stu.getAge());
}
}
}
class Student {
private String name ;
private int age ;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Vector集合
特点:底层是一种可增长的对象数组,所以查询快增删慢,线程安全,执行效率高。
public void addElement(Object obj)------->add(Object obj)
public Enumeration elements():返回此向量的枚举--->相当于:public Iterator iterator()
boolean hasMoreElements() --->boolean hasNext() ;
Object nextElement() --->Object next() ;
可以看出Vector集合和ArrayList集合的常用方法的功能效果是一样,只是,Vector集合操作的是元素,遍历时使用的是枚举,例子(没有写Student类):
import java.util.Enumeration;
import java.util.Vector;
public class Test1 {
public static void main(String[] args) {
//创建对象
Vector<Student> v = new Vector<Student>() ;
Student s1 = new Student("aloha",22) ;
Student s2 = new Student("alohaa",23) ;
Student s3 = new Student("alohaaa",24) ;
//添加元素
v.addElement(s1);
v.addElement(s2);
v.addElement(s3);
//迭代器遍历
Enumeration<Student> elements = v.elements();
while(elements.hasMoreElements()) {
Student str = elements.nextElement() ;
System.out.println(str.getName()+"---" + str.getAge());
}
System.out.println("------------------------");
//size()和get(int index)遍历
for(int x = 0 ;x < v.size() ;x++) {
Student str = (Student)v.get(x) ;
System.out.println(str.getName()+"---" + str.getAge());
}
}
}
LinkedList集合
此集合是List接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素,包括(null)。
LinkedList底层是一种链表,所以查询慢,增删块。线程不安全,不同步,所以执行效率高。
功能:
添加功能
addFirst(Object e):将指定的元素插入到列表的开头
addLast(object e):将指定的元素添加到列表末尾
获取功能:
getFirst():获取列表第一个元素
getLast():获取列表第二个元素
删除功能
public Object removeFirst()移除并返回此列表的第一个元素。
public Object removeLast()移除并返回此列表的最后一个元素。
例子:
import java.util.LinkedList;
public class Test2 {
public static void main(String[] args) {
// 创建对象
LinkedList<Student> ll = new LinkedList<Student>();
Student s1 = new Student("aloha", 22);
Student s2 = new Student("alohaa", 23);
Student s3 = new Student("alohaaa", 24);
Student s4 = new Student("把你插到首位", 233);
Student s5 = new Student("把你插到末位", 666);
Student s6 = new Student("把你插到中间", 555);
// 添加元素
ll.add(s1);
ll.add(s2);
ll.add(s3);
// 遍历
for (Student s : ll) {
System.out.println(s.getName() + "---" + s.getAge());
}
System.out.println("---------------------------");
// 添加功能
ll.addFirst(s4);
ll.addLast(s5);
ll.add(ll.size() / 2, s6);
for (Student s : ll) {
System.out.println(s.getName() + "---" + s.getAge());
}
System.out.println("--------------------------");
// 获取功能
Student sf = ll.getFirst();
Student se = ll.getLast();
System.out.println(
"获取第一个元素: " + sf.getName() + "---" + sf.getAge() + "\n获取最后一个元素: " + se.getName() + "---" + se.getAge());
//删除功能
Student df = ll.removeFirst();
Student de = ll.removeLast();
System.out.println(
"删除并获取第一个元素: " + df.getName() + "---" + df.getAge() + "\n删除并获取最后一个元素: " + de.getName() + "---" + de.getAge());
System.out.println("-----------------\n删除首尾的结果:");
for (Student s : ll) {
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
结果:
使用LinkedList集合的addFirst() 方法可以模拟我们的堆栈操作,因为这个方法是给集合的第一个元素位置增加元素,而打印的时候也是从第一个元素开始遍历。
集合去重的方式
方式一:思想:我们创建两个集合,旧的集合是存放有重复元素的集合,新的集合中存放筛选过后的没有重复的元素。
代码如下:
import java.util.ArrayList;
import java.util.Iterator;
/**
* 集合去重方式一
* @author malaganguo
*
*/
public class Test3 {
public static void main(String[] args) {
ArrayList<String> newList = new ArrayList<String>();
ArrayList<String> oldList = new ArrayList<String>();
oldList.add("nihao") ;
oldList.add("aloha") ;
oldList.add("aloha") ;
oldList.add("hello") ;
oldList.add("kongnixiwa") ;
oldList.add("hi") ;
oldList.add("nihao") ;
//traverse(before)
System.out.print("before: ");
for(String s : oldList) {
System.out.print(s+ " ");
}
//traverse and add to newList
Iterator<String> it = oldList.iterator();
while(it.hasNext()) {
String str = (String)it.next() ;
if(!newList.contains(str)) {//如果新集合中不包含的话,执行if的结构体
newList.add(str);
}
}
//traverse
System.out.print("\nafter:");
for(String s : newList) {
System.out.print(s+ " ");
}
}
}
方式二:(不创建新集合)思想:与创建新集合的思想不同,不创建新集合的方法就是给旧集合中的重复元素删除掉,所以我们需要遍历集合并且将所有元素进行比较,如果比较中 发现有相同元素,那么把相同元素的重复元素删除掉。
代码如下:
import java.util.ArrayList;
import java.util.Iterator;
/**
* 集合去重: 方式二
* @author malaganguo
*
*/
public class Test4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>() ;
list.add("nihao") ;
list.add("aloha") ;
list.add("aloha") ;
list.add("hello") ;
list.add("kongnixiwa") ;
list.add("hi") ;
list.add("nihao") ;
//traverse&delete before
System.out.print("traverse&delete before: ");
for(String s :list) {
System.out.print(s+ " ");
}
/**
* Exception in thread "main"
* checkForComodification
*/
// for(String s1 : list) {
// if(list.contains(s1)) {
// list.remove(s1);
// }
// }
//delete repet
for(int x = 0 ;x <list.size()-1;x++) {
for(int y = x+1 ; y < list.size() ; y++) {
if(list.get(x).equals(list.get(y))) {
list.remove(y) ;
}
}
}
//traverse&delete after
System.out.print("\ntraverse&delete after: ");
for(String s :list) {
System.out.print(s+ " ");
}
}
}
对于对象集合的去重,我们需要比较对象元素是否相同,这个比较和字符串集合比较不同的是,字符串类型重写了equals方法,所以可以直接比较字符串是否相同,但是我们创建的对象集合中并没有重写这个方法,比较的还是地址值,所以无法比较出内容是否相同,需要我们重写euqals方法。
例子:
import java.util.ArrayList;
import java.util.Iterator;
/**
* 需求:使用集合ArrayList存储自定义对象(StudentWithOverride),去除重复的对象(成员变量的值一样,看成一个人)
* @author malaganguo
*
*
* 结果:没有完成需求,并没有在新集合中添加不重复的元素
* 原因:String类中默认重写了equals方法,比较的是数值,而我们自己创建的类中默认equals方法比较的是地址值,所以没有办法完成去重
*/
public class Test5 {
public static void main(String[] args) {
//创建对象
ArrayList<StudentWithOverride> s = new ArrayList<StudentWithOverride>() ;
StudentWithOverride s1 = new StudentWithOverride("aloha", 22);
StudentWithOverride s2 = new StudentWithOverride("alohaa", 23);
StudentWithOverride s3 = new StudentWithOverride("alohaaa", 24);
StudentWithOverride s4 = new StudentWithOverride("我是重复的", 233);
StudentWithOverride s5 = new StudentWithOverride("我是重复的", 233);
StudentWithOverride s6 = new StudentWithOverride("aloha", 22);
//将对象元素加入集合
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
s.add(s6);
//去除重复对象
/**
* 不知道为啥这个就是没有办法去重
*/
//方法一:
// for(int x = 0 ;x < s.size()-1 ;x++) {
// for(int y =x+1 ;y <s.size();y++) {
// if(s.get(x).equals(s.get(y))) {
// s.remove(y) ;
// }
// }
// }
//方法二:创建一个新集合,用迭代器去重
ArrayList<StudentWithOverride> newList = new ArrayList<StudentWithOverride>();
Iterator<StudentWithOverride> it = s.iterator();
while(it.hasNext()) {
StudentWithOverride stu = it.next();
if(!newList.contains(stu)) {
newList.add(stu) ;
}
}
//遍历
Iterator<StudentWithOverride> it2 = newList.iterator();
while(it2.hasNext()) {
StudentWithOverride ss = it2.next() ;
System.out.println(ss.getName()+ "---"+ ss.getAge());
}
}
}
class StudentWithOverride{
private String name ;
private int age ;
public StudentWithOverride() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public StudentWithOverride(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override //为什么字符串去重没有问题,而我们自己定义的类对象就没有办法去重呢?因为String类型默认重写了equals方法。
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentWithOverride other = (StudentWithOverride) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
这样就可以实现非String类型的对象去重了!
针对数组操作的工具类:Arrays,提供了一个方法:
public static <T> List<T> asList(T... a) :将数组转换成固定大小的集合
import java.util.List;
import java.util.Arrays;
/**
* Arrays提供的从数组转变成集合的方法:
* public static <T> List<T> asList(T... a) :将数组转换成固定大小的集合
* 缺点:集合的长度固定,不能再改变了
* @author malaganguo
*
*/
public class Test5 {
public static void main(String[] args) {
//将字符串数组转换位String类型的List集合
List<String> list = Arrays.asList("hello","world","java","!") ;
// list.add("javaee");//会报错java.lang.UnsupportedOperationException
// list.remove("hello") ;//会报错java.lang.UnsupportedOperationException
list.set(0, "nihao");
for(String str : list) {
System.out.println(str);
}
/**输出结果:
* nihao
* world
* java
* !
*/
}
}
泛型
当我们需要给对象中存储元素时,由于集合中只能存储相同类型的元素,假如我们在集合中存储了String 类型的元素和int类型的元素,那么我们在编译的时候时没有问题的,但是在运行的时候就会报错,为了防止出现其他类型的元素通过了编译,我们 引入了泛型,泛型可以规定我们集合的存储类型。用法<这里是引用数据类型>,将明确集合类型的工作推迟到了创建对象或者调用方法的时候,属于一种参数化类型,可作为参数传递。
泛型的好处:
(1)解决了黄色警告线问题!
(2)将运行时期的异常提前到了编译时期!
(3)避免了强制类型转换!
可见,泛型提高了程序的安全性。
将泛型定义在类上,成员位置上
我们在创建一个类的时候,可以将泛型定义在这个类上,这样,我们就规定了类中的成员的类型,我们在创建这个类的对象的时候只需要知名这个类的泛型,那么,在我们下面使用对象做事情的时候就会出现类型锁定的情况,即只能使用我们泛型中规定的类型。
例子:
/**
* 将泛型定义在类上
* @author malaganguo
*
*/
class Student<T>{
private T name ;
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
public T print(T a ,T b) {
T c = b ;
return c;
}
}
public class Test1 {
public static void main(String[] args) {
Student<String> stu = new Student<String>() ;
stu.setName("aloha");
System.out.println(stu.print("haha", "233"));
System.out.println(stu.getName());
}
}
泛型高级——通配符
<?>代表任意类型,如Object类型或者java类
<? extends E> 向下限定E的子类或者E这个类型
<? super E>向上限定,E类型以及其父类
集合的嵌套遍历
即大集合中包含小集合,那么大集合的泛型位集合类型,小集合的类型为我们定义的类型。嵌套集合的思想:首先创建一个大集合和n个小集合,给每个小集合中添加元素,然后将各个小集合添加到大集合中,这就完成了集合的嵌套。关于集合的嵌套遍历,我们使用增强for循环(传送门:https://blog.csdn.net/weixin_38930706/article/details/80250301)的嵌套:我们的第一层增强for循环用来遍历小集合,将遍历的小集合传给一个新集合对象,然后第二层增强for循环遍历第一层中的新集合对象,将元素便利出来,输出打印。
代码:(部分)
import java.util.ArrayList;
/**
* 集合的嵌套遍历
* @author malaganguo
*
*/
public class Test1 {
public static void main(String[] args) {
//创建一个大集合,这个集合中存放着小集合,那么大集合的泛型是一个集合类型
ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>() ;
//创建两个小集合
ArrayList<Student> arrayList1 = new ArrayList<Student>() ;
ArrayList<Student> arrayList2 = new ArrayList<Student>();
//创建四个学生对象
Student s1 = new Student("你好", 22);
Student s2 = new Student("ALOHA", 23);
Student s3 = new Student("hello", 24);
Student s4 = new Student("nihao", 25);
//将创建的对象加入集合中
arrayList1.add(s1);
arrayList1.add(s2);
arrayList2.add(s3);
arrayList2.add(s4);
//将两个小集合加入到大集合中
bigArrayList.add(arrayList1);
bigArrayList.add(arrayList2);
//遍历
for(ArrayList<Student> al : bigArrayList) {
for(Student stu1 : al) {
System.out.println(stu1.getName()+ "---" + stu1.getAge());
}
}
}
}