目录
一、List接口的子类
1、ArrayList类
ArrayList类的底层逻辑是数组。具有查询快,增删慢的特点,线程不安全,效率高
ArrayList案例:
需求一:使用ArrayList存储字符串并遍历(如果有重复的需要去除)
代码实现:
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayTest1 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("hello");
arrayList.add("world");
arrayList.add("java");
arrayList.add("bigdata");
arrayList.add("hive");
arrayList.add("spark");
arrayList.add("bigdata");
System.out.println("去重之前的集合:"+arrayList);
// 创建第二个集合对象存放去重之后的集合
ArrayList list2 = new ArrayList();
// 创建迭代器对象
Iterator iterator = arrayList.iterator();
// 遍历
while(iterator.hasNext()){
String s=(String)iterator.next();
if(!list2.contains(s)){
list2.add(s);
}
// 如果list2中没有该元素,就添加该元素到list2集合中
}
System.out.println("去重之后的集合:"+list2);
}
}
这里集合中bigdata元素重复了一次,需要去除,输出结果:
需求二:使用ArrayList存储自定义对象并遍历(并去重)
学生对象,姓名和年龄都一样的时候,表示的是同一个人
代码实现:
先创建学生类:
public class Students {
private String name;
private int age;
public Students() {
}
public Students(String name, int age) {
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;
}
@Override
public String toString() {
return "Students{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
再定义ArrayList类进行进一步操作:
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayTest2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
Students s1 = new Students("张翼德", 20);
Students s2 = new Students("赵云", 17);
Students s3 = new Students("张翼德", 20);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println("去重前的集合:");
System.out.println(list);
ArrayList list2 = new ArrayList();//定义第二个集合存储去重后的集合
Iterator iterator = list.iterator();
// 遍历
while(iterator.hasNext()){
Students s=(Students)iterator.next();
if(!list2.contains(s)){
list2.add(s);
}
}
System.out.println("去重后的集合:");
System.out.println(list2);
}
}
输出结果:
根据输出结果来看,虽然实现了遍历,但是并没有实现去重效果,通过分析发现可能是再if判断中出现了问题。
分析:if语句行,只有当if语句为true时,才会执行添加功能,根据输出结果来看,if语句始终是true,也就是说contains方法并没有生效。这是需要进入到contains方法底层实现中去查看
以下为contains的底层实现:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))//调用的是equals方法
return i;
}
return -1;
}
通过观察底层实现发现contains底层调用的是equals方法,而上述Students类中并没有重写equals方法,因此这里调用的是Object类中的equals方法,故比较的是地址值,学生对象都是new出来的,所以对象地址值必然不一样。故equals结果永远为false,回到if语句中加上!就永远为true,所以无论如何都会添加到新集合中,最终没有实现去重。
解决办法:在元素类Students加入重写equals方法即可,可自动生成。其他代码不变。
//重写的equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Students students = (Students) o;
return age == students.age && Objects.equals(name, students.name);
}
输出结果:
2、Vector类
底层数据结构是数组,查询快,增删慢,线程安全,效率低(虽然安全,但实际开发不使用)
Vector类特有的方法
public void addElement(Object obj) 将元素添加到集合的末尾 效果上和add()一样
public Object elementAt(int index) 获取指定索引处的元素
get(int index) public Enumeration elements() 返回此向量的组件的枚举。
Vector类举例实现与ArrayList类基本相同,只是方法名不同而已。
代码举例:
import java.util.Enumeration;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
//创建Vector集合对象
Vector vector = new Vector();
//向集合添加元素
vector.addElement("hello");
vector.addElement("java");
vector.add("world");
vector.addElement("java");
// System.out.println(vector);
//public Object elementAt(int index)获取指定索引处的元素 get(int index)
Object o = vector.elementAt(0);
System.out.println(o);
System.out.println(vector.elementAt(1));
System.out.println(vector.elementAt(2));
System.out.println(vector.elementAt(3));
// System.out.println(vector.elementAt(4));
System.out.println(vector.get(3));
System.out.println("=============================================");
//public Enumeration elements() 返回此向量的元素的枚举。
//简单记忆 你就把这个对象看作成一个迭代器
Enumeration elements = vector.elements();
while (elements.hasMoreElements()) {
Object o1 = elements.nextElement();
String s = (String) o1;
System.out.println(s);
}
}
}
3、LinkedList类
底层数据结构是双链表,查询慢,增删快。线程是不安全的,效率高
LinkedList类中的特有方法
1、添加功能:
public void addFirst(Object e) 在集合的开头添加元素
addLast(Object e) 在结合末尾添加元素,等同于add()方法
2、获取功能:
public Object getFirst() 获取集合中的第一个元素
getLast() 获取集合中的最后一个元素
3、删除功能:
public Object removeFirst() 从集合中删除第一个元素并返回
public Object removeLast() 从集合中删除最后一个元素并返回
具体功能实现代码举例:
import java.util.LinkedList;
public class LinkedTest1 {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);
// 在集合开头添加元素
list.addFirst("bigdata");
System.out.println("开头添加元素:");
System.out.println(list);
// 在集合末尾添加元素
list.addLast("superman");
System.out.println("末尾添加元素:");
System.out.println(list);
// 获取集合第一个元素
System.out.println("获取第一个元素:"+list.getFirst());
System.out.println(list);
// 获取集合最后一个元素
System.out.println("获取最后一个元素:"+list.getLast());
System.out.println(list);
// 删除第一个元素
System.out.println("删除第一个元素"+list.removeFirst());
System.out.println("删除后的集合:"+list);
// 删除最后一个元素
System.out.println("删除最后一个元素:"+list.removeLast());
System.out.println("删除后的集合:"+list);
}
}
输出结果:
案例:
需求:
请使用LinkedList模拟栈数据结构的集合,并测试
分析:题意是需要我们自己设计一个集合类,它的底层逻辑实现是LinkedList类,再调用自己的方法去实现栈数据结构
代码实现:
自己设计的集合类MineStack:
import java.util.LinkedList; public class MineStack { private LinkedList linkedList; //无参构造,底层为LinkedList无参构造创建对象 MineStack(){ LinkedList linkedList = new LinkedList(); } // 底层调用linkedList中的添加第一个元素 void Mineadd(Object obj){ linkedList.addFirst(obj); } public boolean ismyEmpty(){ return linkedList.isEmpty(); } // 底层调用为删除第一个元素并返回 public Object mineGet(){ return linkedList.removeFirst(); } }
由于栈数据结构的特点是先进后出,所以我们需要使用LinkedList类中的removeFirst方法删除第一个元素并返回,这样第二个元素就变成了第一个元素,在下一次遍历时就可以输出该元素,最终实现先进后出,直到集合为空停止
测试类MineStackTest
public class MIneStackTest { public static void main(String[] args) { // 创建对象 MineStack stack = new MineStack(); // 添加数据到集合 stack.Mineadd("hello"); stack.Mineadd("world"); stack.Mineadd("java"); stack.Mineadd("bigdata"); // 遍历判断是否含有元素.含有就删除第一个元素并输出该元素 while(!stack.ismyEmpty()){ Object o = stack.mineGet(); System.out.println(o); } } }
输出结果: