本章所涉及到的数据结构知识可在数据结构学习记录中学习:
咖啡ice的数据结构学习记录
没有使用“泛型”之前,Collection中可以存储Object中的所有子类型。
集合不能直接存储基本数据类型,也不能存储java对象。只能存储java对象的内存地址。
Collection中常用方法:
往集合里加元素:boolean add(Object e)
获取集合中元素个数:int size()
清空集合:void clear()
判断集合是否包含元素:boolean contains(Object o)
删除集合中某个元素:boolean remove(Object o)
判断集合是否为空:boolean isEmpty()
把集合转换成数组:Object[] toArray()
package collection;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest {
public static void main(String[] args) {
//创建一个集合对象
//Collection c = new Collection(); 接口是抽象的,无法实例化
Collection c = new ArrayList<>();//用一个父类型指向子类型。
c.add(1200);//自动装箱,实际上放进去了一个对象的内存地址Integer x = new Integer(1200);
c.add(new Object());
System.out.println("集合中元素个数:"+ c.size()); //集合中元素个数:2
//清空集合
c.clear();
System.out.println("集合中元素个数:"+ c.size()); //集合中元素个数:0
c.add("ice");
c.add("coffee");
c.add("is");
c.add("perfect");
boolean flag = c.contains("coffee");
System.out.println(flag); //true
boolean flag2 = c.contains("coffee2");
System.out.println(flag2); //false
System.out.println("集合中元素个数:"+ c.size()); //集合中元素个数:4
c.remove("is");
System.out.println("集合中元素个数:"+ c.size()); //集合中元素个数:3
System.out.println(c.isEmpty()); //false
c.clear();
System.out.println(c.isEmpty()); //true
c.add("abc");
c.add("def");
c.add(100);
c.add("ice-coffee");
Object[] objs = c.toArray();
for (int i = 0; i < objs.length; i++) {
System.out.printf(objs[i] + " "); //abc def 100 ice-coffee
}
}
}
所有Collection通用的一种方法:迭代方式(也就是遍历)。
在Map集合中不能用迭代器,而在Collection以及子类中使用。
迭代器定义的变量类似于指针,且不是指向第一个元素。,可以使用两个方法来迭代对象Iterator中方法:
? boolean hasNext() 如果仍有元素可以迭代(遍历),则返回true。如果false表示没有更多元素可以迭代。
? Object next() 返回迭代的下一个元素。
注:也就是说迭代器对象指向要输出位置的前一个位置。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new ArrayList();
//存储时的类型和取出的类型一样
c.add("ice");
c.add("coffee");
c.add(100);
Iterator it = c.iterator();
while(it.hasNext()){ //下一个元素存在,返回true
System.out.printf(it.next() + " "); //ice coffee 100
}
}
}
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new HashSet();
//存进去和取出来顺序不一样
c.add(100);+
c.add(200);
c.add(300);
c.add(100);
c.add(40);
Iterator it = c.iterator();
while(it.hasNext()){
System.out.printf(it.next() + " "); //100 200 40 300
}
}
}
contains()方法:
boolean contains(Object o):判断集合中是否包含某个对象o,如果包含返回true,如果不包含返回false。
注:在底层中,contains()方法调用equals()方法,所以放在集合里边的对象需要重写equals()方法。
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(new String("abc"));
c.add(new String("def"));
String x = new String("abc"); //由于String对象在new时会放到字符串常量池,创建相同的字段时会指向同一个位置。
System.out.println(c.contains(x)); //true
User u1 = new User("coffee");
User u2 = new User("coffee");
c.add(u1);
System.out.println(c.contains(u2));//这里没有重写,这个结果比较的是内存地址,结果是:false
}
}
class User{
private String name;
public User(){
}
public User(String name){
this.name = name;
}
}
contains方法在底层会调用equals方法进行比较,所以这里对象重写了equals方法则会是true
public class CollectionTest {
public static void main(String[] args) {
Collection c = new ArrayList();
User u1 = new User("coffee");
User u2 = new User("coffee");
c.add(u1);
System.out.println(c.contains(u2)); //true
}
}
class User{
private String name;
public User(){ }
public User(String name){ this.name = name; }
//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name);
}
}
remove()方法:
boolean remove(Object o):删除集合中包含某个对象o,如果包含返回true,如果不包含返回false。
注:在底层中,remove()方法调用equals()方法,所以放在集合里边的对象需要重写equals()方法。
public class CollectionTest01 {
public static void main(String[] args) {
Collection c = new ArrayList();
String s1 = new String("hello");
String s2 = new String("hello");
c.add(s1);
c.remove(s2);
System.out.println(c.size()); //0
}
}
List集合特点:每个元素有下标(下标从0开始),可以有重复元素。相当于数据结构中的线性表(数组)。
List作为Collection的子接口,list接口有自己常用的特色方法:
在指定位置插入指定元素:void add(int index,E element)
返回指定下标元素:E get(int index)
返回元素第一次出现索引:int indexOf(Object o)
返回元素最后一次出现索引:int lastIndexOf(Object o)
移除指定下标元素:E remove(int index)
用指定元素替换指定位置元素:E set(int index,E element)
package list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListTest{
public static void main(String[] args) {
//创建list类型集合
List mylist = new ArrayList();
//add()默认在数组末尾添加元素
mylist.add("ice");
mylist.add("coffee");
mylist.add("is");
mylist.add("nice");
Iterator it = mylist.iterator();
while(it.hasNext()){
Object elt = it.next();
System.out.printf(elt + " "); //ice coffee is nice
}
System.out.println(); //分割线
//add(index,element)在指定位置插入添加指定元素
//这个方法使用效率低,使用情况较少
mylist.add(1,"milk");
Iterator it2 = mylist.iterator();
while(it2.hasNext()){
Object elt = it2.next();
System.out.printf(elt + " "); //ice milk coffee is nice
}
System.out.println();//分割线
//根据下标获取元素get()方法
System.out.println(mylist.get(0)); //ice
//由于List有下标,List有独特的遍历方式for循环
for (int i = 0; i < mylist.size(); i++) {
System.out.printf(mylist.get(i) + " "); //ice milk coffee is nice
}
System.out.println();//分割线
//获取指定对象第一次出现处索引
System.out.println(mylist.indexOf("is")); //3
mylist.add(3,"coffee");
//获取指定对象最后一次出现索引
System.out.println(mylist.lastIndexOf("coffee")); //3
//删除指定下标位置的元素
mylist.remove(2);
mylist.remove(1);
for (int i = 0; i < mylist.size(); i++) {
System.out.printf(mylist.get(i) + " "); //ice coffee is nice
}
System.out.println();//分割线
//修改指定位置元素
mylist.set(3,"good");
for (int i = 0; i < mylist.size(); i++) {
System.out.printf(mylist.get(i) + " "); //ice coffee is good
}
}
}
注:计算机英语常用增删改查几个单词
增:add、save、new
删:delete、drop
改:update、set、modify
查:find、get、query、select
ArrayList特性:
①ArrayList集合初始化容量是10。
②ArrayList集合底层是Object类型的数组Object[]。
③构造方法:new ArrayList(); 或者 List list2 = new ArrayList(20);
④一般给定一个预估价初始化容量,减少数组扩容次数。每次扩容会扩1.5倍。
⑤数组检索效率高,使用频率最多。
⑥随机增删元素效率比较低。但是在末尾增加效率高不受影响。
⑦ArrayList是非线程安全的
package list;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class ArrayListTest {
public static void main(String[] args) {
//默认初始化容量10
List list1 = new ArrayList();
//size()方法是获取当前集合中元素个数,而不是获取集合容量。
System.out.println(list1.size()); //0
//指定初始化容量
List list2 = new ArrayList(20);
//通过构造方法将HashSet集合转换成List集合
Collection c = new HashSet();
c.add("ice");
c.add("coffee");
List list3 = new ArrayList(c);
for (int i = 0; i < list3.size(); i++) {
System.out.printf(list3.get(i) + " "); //coffee ice
}
}
}
public class ArrayListTest {
public static void main(String[] args) {
List mylist = new ArrayList();
Collections.synchronizedList(mylist);
mylist.add("111");
}
}
LinkedList底层为双向链表数据结构。LinkedList集合底层也是有下标的,不过底层是双向链表,所以查找效率较低。
与ArrayList对比:
LinkedList在检索(查找)效率较低,在增删方面效率较高。
ArrayList在检索(查找)效率较高,在增删方面效率较低。不过只在末尾添加元素时效率还是很高的。
所以ArrayList比较常用。
import java.util.LinkedList;
import java.util.List;
public class LinkedListTest01 {
public static void main(String[] args) {
List list = new LinkedList();
list.add("ice");
list.add("coffee");
for (int i = 0; i < list.size(); i++) {
System.out.printf(list.get(i) + " ");
}
}
}
import java.util.Iterator;
import java.util.Vector;
public class VectorTest {
public static void main(String[] args) {
Vector vector = new Vector();
vector.add(1);
vector.add(2);
vector.add(3);
vector.add(4);
vector.add(5);
vector.add(6);
vector.add(7);
vector.add(8);
vector.add(9);
vector.add(10);
Iterator it = vector.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.printf(obj + " "); //1 2 3 4 5 6 7 8 9 10
}
}
}
JDK5.0后推出的新特性:泛型
在没有使用泛型时,it.next()取出来的是Object类型,使用起来不方便。
public class GenericTest {
public static void main(String[] args) {
List myList = new ArrayList();
Cat c = new Cat();
Bird b = new Bird();
myList.add(c);
myList.add(b);
Iterator it = myList.iterator();
while(it.hasNext()){
// Animal a = it.next();迭代器取出的是Object,所以这么写会报错
Object obj = it.next();
if(obj instanceof Animal){
Animal a = (Animal)obj;
a.move();
}
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Bird extends Animal{
public void fly(){
System.out.println("鸟在飞");
}
}
public class GenericTest {
public static void main(String[] args) {
List<Animal> myList = new ArrayList<Animal>();
Cat c = new Cat();
Bird b = new Bird();
myList.add(c);
myList.add(b);
//myList.add("abc");只能存储Animal类型的数据,不允许存储String或其他类型
//这个表示迭代器迭代的是Animal类型
Iterator<Animal> it = myList.iterator();
while(it.hasNext()){
//使用泛型后,每一次迭代返回的数据都是Animal类型
Animal a =it.next();
//不需要强制类型转换,直接调用
a.move();
}
}
}
class Animal{
public void move(){
System.out.println("动物在移动");
}
}
class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Bird extends Animal{
public void fly(){
System.out.println("鸟在飞");
}
}
public class GenericTest {
public static void main(String[] args) {
List<Animal> myList = new ArrayList<>();
myList.add(new Animal());
myList.add(new Cat());
myList.add(new Bird());
//myList.add("abc");只能存储Animal类型的数据,不允许存储String或其他类型
Iterator<Animal> it = myList.iterator();
while(it.hasNext()){
Animal a = it.next();
a.move();
}
}
}
public class GenericTest<E> {
public void doSome(E o){
System.out.println(o);
}
public static void main(String[] args) {
GenericTest<String> gt = new GenericTest<>();
gt.doSome("icecoffee");
//gt.doSome(123); 报错,类型不匹配
GenericTest<Integer> gt2 = new GenericTest<>();
//gt2.doSome("icecoffee");报错,类型不匹配
gt2.doSome(123);
}
}
增强for(foreach)语法:变量名是用来标记数组中的元素。
for(元素类型 变量名 : 数组名){ }
public class ForEachTest {
public static void main(String[] args) {
int[] arr = {123,11,4,1453,45,21};
for(int data : arr){
System.out.printf(data + " "); //123 11 4 1453 45 21
}
}
}
public class ForEachTest {
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.add("ice");
myList.add("coffee");
myList.add("is");
myList.add("nice");
for (String s: myList) {
System.out.printf(s + " "); //ice coffee is nice
}
}
}
public class SetTest {
public static void main(String[] args) {
Set<String> strs = new HashSet<>();
//HashSet中add实际上是存储到HashMap的key部分。
strs.add("ice");
strs.add("coffee");
strs.add("coffee");
strs.add("very");
strs.add("good");
strs.add("very");
strs.add("good");
for (String s:
strs) {
System.out.printf(s + " "); //very coffee ice good
}
}
}
public class SetTest {
public static void main(String[] args) {
Set<String> strs = new TreeSet<>();
strs.add("A");
strs.add("C");
strs.add("V");
strs.add("R");
strs.add("N");
strs.add("J");
strs.add("O");
for (String s:
strs) {
System.out.printf(s + " "); //A C J N O R V
}
}
}
——本章节为个人学习笔记。学习视频为动力节点Java零基础教程视频:动力节点—JAVA零基础教程视频