需求:使用ArrayList存储字符串并遍历(如果字符串有重复的需要去除)
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo1 {
public static void main(String[] args) {
//创建集合对象
ArrayList list = new ArrayList();
//向集合中添加字符串元素
list.add("hello");
list.add("world");
list.add("java");
list.add("hadoop");
list.add("hive");
list.add("hello");
list.add("spark");
list.add("java");
list.add("world");
System.out.println("去重之前的集合为:" + list);
//创建一个新的集合去保存去重后的元素
ArrayList list1 = new ArrayList();
//遍历旧的集合
Iterator iterator = list.iterator();
while (iterator.hasNext()){
String s=(String) iterator.next();
//获取到元素之后,拿着这个元素去新集合中查找,如果找到说明重复,就不添加,反之添加到新集合中
if (!list1.contains(s)){
list1.add(s);
}
}
System.out.println("去重后集合为:"+list1);
}
}
结果:
去重之前的集合为:[hello, world, java, hadoop, hive, hello, spark, java, world]
去重后集合为:[hello, world, java, hadoop, hive, spark]
使用ArrayList存储自定义对象并遍历(并去重)
学生对象:姓名和年龄都一样的时候,表示是同一个人。 我们按照处理字符串重复的逻辑来处理自定义对象重复,发现结果并没有进行去重 为什么呢? 要想知道为什么,就得知道问题出现在了哪一行代码中。 经过简单地分析后发现,问题出现了在判断是否包含的那一行代码中 因为只有当if语句为true的时候,才会将元素添加到新集合中 说明我们这里判断,一直都是为true的,换句话contains这个方法并没有生效 要搞清楚为什么不会生效,就得搞清楚contains这个方法底层是怎么做的。 contains方法底层调用的是equals方法,但是呢,Student类中并没有重写equals方法 所以调用的是Object类中的equals方法,而Object类中的equals方法比较的是地址值,学生对象都是new出来的 地址值必然不一样,equals比较的结果永远是false,加上我们代码中的!,结果永远是为true,所以无论如何都会添加到 新集合中,最终结果没有去重。 解决方法:元素类重写equals()方法 自动生成即可
这里需要在Student类里元素类重写equals()方法
Student类:
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(){
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
ArrayListDemo2
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo2 {
public static void main(String[] args) {
//创建集合对象
ArrayList list = new ArrayList();
//创建学生对象
Student s1 = new Student("王宇", 18);
Student s2 = new Student("明旺", 17);
Student s3 = new Student("周家祥", 19);
Student s4 = new Student("张保桂", 20);
Student s5 = new Student("王宇", 18);
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
System.out.println(list);
System.out.println("===========================");
ArrayList list1 = new ArrayList();
Iterator iterator = list.iterator();
while (iterator.hasNext()){
Student s=(Student) iterator.next();
if (!list1.contains(s)){
list1.add(s);
}
}
System.out.println(list1);
}
}
结果:
[Student{name='王宇', age=18}, Student{name='明旺', age=17}, Student{name='周家祥', age=19}, Student{name='张保桂', age=20}, Student{name='王宇', age=18}]
===========================
[Student{name='王宇', age=18}, Student{name='明旺', age=17}, Student{name='周家祥', age=19}, Student{name='张保桂', age=20}]
Vector了解即可:
Vector: 底层数据结构是数组,查询快,增删慢 线程安全,效率低(虽然它是线程安全的,我们今后也不会去使用它,后面会说一个线程安全的类代替它) Vector特有的方法: public void addElement(Object obj) 将元素添加到集合的末尾 效果上和add()一样 public Object elementAt(int index) 获取指定索引处的元素 get(int index) public Enumeration elements() 返回此向量的组件的枚举。
import java.util.Enumeration;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
//创建对象
Vector vector = new Vector();
//向集合中添加元素
vector.addElement("hello");
vector.addElement("java");
vector.add("world");
vector.addElement("java");
System.out.println(vector);
System.out.println("=====================");
//public Object elementAt(int index)获取指定索引处的元素 get(int index)
Object o = vector.elementAt(0);
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()){
String s=(String) elements.nextElement();
System.out.println(s);
}
}
}
结果:
[hello, java, world, java]
=====================
java
world
java
java
=====================
hello
java
world
java
LinkedList:
1、底层数据结构是双链表,查询慢,增删快
2、线程是不安全的,效率高
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 LinkListDemo1 {
public static void main(String[] args) {
//创建集合对象
LinkedList linkedList = new LinkedList();
//向集合里添加元素
linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");
linkedList.add("bigdata");
linkedList.add("hadoop");
linkedList.add("hive");
System.out.println(linkedList);
System.out.println("================");
//public void addFirst(Object e) 在集合的开头添加元素
linkedList.addFirst("spark");
System.out.println(linkedList);
//addLast(Object e) 在结合末尾添加元素,等同于add()方法
linkedList.addLast("Flink");
System.out.println(linkedList);
//public Object getFirst() 获取集合中的第一个元素
Object first = linkedList.getFirst();
System.out.println(first);
System.out.println(linkedList);
//public Object getLast() 获取集合中的最后一个元素
Object last = linkedList.getLast();
System.out.println(last);
System.out.println(linkedList);
//public Object removeFirst() 从集合中删除第一个元素并返回
Object o = linkedList.removeFirst();
System.out.println(o);
System.out.println(linkedList);
//public Object removeLast() 从集合中删除最后一个元素并返回
Object o1 = linkedList.removeLast();
System.out.println(o1);
System.out.println(linkedList);
}
}
结果:
[hello, world, java, bigdata, hadoop, hive]
================
[spark, hello, world, java, bigdata, hadoop, hive]
[spark, hello, world, java, bigdata, hadoop, hive, Flink]
spark
[spark, hello, world, java, bigdata, hadoop, hive, Flink]
Flink
[spark, hello, world, java, bigdata, hadoop, hive, Flink]
spark
[hello, world, java, bigdata, hadoop, hive, Flink]
Flink
[hello, world, java, bigdata, hadoop, hive]
请用LinkedList模拟栈数据结构的集合,并测试
栈的特点:先进后出 题目真正的意思是,自己写一个集合类,底层是LinkedList,调用自己定义的方法实现栈数据结构。
import java.util.Iterator;
import java.util.LinkedList;
public class LinkListTest1 {
public static void main(String[] args) {
//创建集合对象
LinkedList linkedList = new LinkedList();
// 添加元素
// linkedList.add("hello");
// linkedList.add("world");
// linkedList.add("java");
linkedList.addFirst("hello");
linkedList.addFirst("world");
linkedList.addFirst("java");
//遍历
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
//如果面试的时候,遇到这样的题目
//按照上面的做法,一分都没有
}
}
结果:
java
world
hello
自己创建类:
import java.util.LinkedList;
public class MyStack {
private LinkedList linkedList;
MyStack() {
linkedList = new LinkedList();
}
public void myAdd(Object obj) {
linkedList.addFirst(obj);
}
public Object myGet() {
// return linkedList.getLast();
return linkedList.removeFirst();
}
public boolean myisEmpty() {
return linkedList.isEmpty();
}
}
测试自己定义集合类,底层是LinkedList
public class MyStackTest {
public static void main(String[] args) {
//创建自己定义的集合类
MyStack myStack = new MyStack();
//添加元素到集合
myStack.myAdd("hello");
myStack.myAdd("world");
myStack.myAdd("java");
myStack.myAdd("bigdata");
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());
// System.out.println(myStack.myGet());//会报错
//应该在获取元素之前判断集合中还有没有元素
while (!myStack.myisEmpty()){
Object o = myStack.myGet();
System.out.println(o);
}
}
}
结果:
bigdata
java
world
hello
ClassCastException: 类型转换异常 我们按照正常的写法,在集合中添加一些不同的数据类型的数据,在遍历的时候进行向下转型的时候,发生了错误。 为什么呢? 因为我们在存储数据的时候,不光存储了字符串类型的数据,还存储了Integer类型,Double类型,Student类型的数据。 但是呢,我们在遍历的时候,将获取到的元素都转换成字符串类型,但是,数据的类型不一致导致发生异常。 如果说在我们存储数据的时候,告诉我们只能存储字符串类型的数据,将来再做强转的时候,就不会报错了。 想一想,我们之前学过的数组,在定义的时候,就限定了一个数组只能存放同一种数据类型的数据。 String[] arr = new String[3]; arr[0] = "0";
// arr[1] = new Student();
如果java中的集合模仿着数据,也搞出这样限定数据类型的做法,在创建集合的时候就明确存放一类数据类型就好了。
这样的话,在后面向下转型的时候,就不会发生异常了。
这样的技术,java提供了一个东西叫做:泛型。
泛型: 把明确数据类型的工作,提前到了编译时期,在创建集合的时候明确存储元素的数据类型。 这样的做法有点向把数据类型当作参数一样传递,所以泛型还有一个叫法:参数化类型 泛型的语句定义格式: <引用数据类型> 注意:尖括号中的数据类型只能是引用数据类型 泛型的好处: 1、将我们运行时期出现的问题,提前到编译时期 2、不需要做强制类型转换 3、优化了代码。消除了不必要的黄色警告线,使代码看起来更简洁 通过观察API发现,泛型可以出现在类,接口,方法上面,我们看到的类似于<E>这样的都叫泛型,一般来说,泛型出现大多使用的集合中。
public class GenericDemo {
public static void main(String[] args) {
//创建一个List集合对象
//在JDK1.7之后,泛型会进行自动类型推断
ArrayList<String> list = new ArrayList<String>();
//向集合中添加元素
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
list.add("hello");
// list.add(20);
// list.add(12.34);
// list.add(new Student());
//遍历
// Iterator iterator = list.iterator();
// while (iterator.hasNext()) {
// Object next = iterator.next();
//
// String s = (String) next; //ClassCastException
//
// System.out.println(next);
// }
//遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
}
结果:
hello
hello
hello
hello
hello