容器(Collection)
数组就是一种容器,可以在其中放置对象或基本类型数据。
优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。
劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。
泛型(类似C++中的模板)
就是“数据类型的参数化”。可以把“泛型”理解为数据类型的一个占位符(形式参数),即告诉编译器,在嗲用泛型时必须传入实际类型。
package cn.Tony.Package;
public class TestGeneric {
public static void main(String[] args) {
Mycollection<String> mc = new Mycollection<String>();//实际参数
mc.set("yhq",0);
//mc.set(8888,1);
//Integer a = (Integer)mc.get(1);
String b = (String)mc.get(0);
AddNumber<Integer> addNumber = new AddNumber();
addNumber.addnum(10,20);
System.out.println(addNumber.addnum(10,20));
}
}
class Mycollection<E>{//E为通用数据类型,相当于形式参数,可以写多个
Object[] objs = new Object[5];
public void set(E obj,int index){
objs[index] = obj;
}
public E get(int index){
return (E)objs[index];
}
}
class AddNumber<E>{
public E addnum(Integer num1,Integer num2){
return (E)num1;
}
}
Collection接口
Collection是一个容器,是各种数据结构的泛型。
public static void test01(){
Collection<String> c = new ArrayList<>();
System.out.println(c.size());
System.out.println(c.contains("尼"));
c.add("WDNMD");
c.add("PDD");
c.clear();
c.remove("PDD");//将容器中对象的地址移除,实际的对象还是存在的
System.out.println(c);
}
public static void test02(){
List<String> list01 = new ArrayList<>();
list01.add("aa");
list01.add("bb");
list01.add("cc");
List<String>list02 = new ArrayList<>();
list02.add("aa");
list02.add("ee");
list02.add("kk");
list01.addAll(list02);
}
ArrayList手动实现
package cn.lxk.mycollection;
import javax.management.RuntimeErrorException;
import java.util.Arrays;
public class YhqArrayList02<E> {
private Object[] elementData;
private int size;
private static final int DEFALT_CAPACITY = 10;
public YhqArrayList02() {
elementData = new Object[DEFALT_CAPACITY];
}
//数组初始化
public YhqArrayList02(int capacity) {
if (capacity<0){
throw new RuntimeException("容器容量不能为负数");
}else if (capacity==0){
elementData = new Object[DEFALT_CAPACITY];
}else {
elementData = new Object[capacity];
}
elementData = new Object[capacity];
}
//数组扩容
public void add(E obj) {
if (size==elementData.length){
Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
System.arraycopy(elementData,0,newArray,0,elementData.length);
elementData = newArray;//使得旧数组回收
}
elementData[size++] = obj;
}
public E get(int index){
return (E) elementData[index];
}
public void set(E element,int index){
checkRange(index);
elementData[index] = element;
}
//索引合法判断
public void checkRange(int index){
if (index<0||index>size-1){
throw new RuntimeException("索引不合法");//抛出运行时异常
}
}
public void remove(E element){
for (int i = 0;i<size;i++){
if (element.equals(get(i))){ //容器中所有的比较操作都是用equals
//将该元素从中移除
remove(i);
}
}
}
//数组元素删除
public void remove(int index){
int numMoved = elementData.length-index-1;
if (numMoved>0){
System.arraycopy(elementData,index+1,elementData,index,numMoved);
}
elementData[--size] = null;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0?true:false;
}
@Override
public String toString() {
return "YhqArrayList{" +
"elementData=" + Arrays.toString(elementData) +
", size=" + size +
'}';
}
public static void main(String[] args) {
YhqArrayList02 s2 = new YhqArrayList02();
for (int i = 0;i<40;i++){
s2.add("Y"+i);
}
s2.set("YHQ",15);
s2.remove(11);
System.out.println(s2.toString());
System.out.println(s2.get(10));
}
}
LinkList手动实现
package cn.lxk.mycollection;
public class LinkList<E> {
private Node first;
private Node last;
private int size;
public void insert(int index,E element){
Node node = new Node(element);
Node temp = null;
temp = getNode(index);
node.previous = temp.previous;
node.next = temp;
temp.previous.next = node;
temp.previous = node;
}
public void remove(int index){
checkRange(index);
Node temp = getNode(index);
if (temp!=null){
Node up = temp.previous;
Node down = temp.next;
if (up!=null){
up.next = down;
}
if (down!=null){
down.previous = up;
}
if (index==0){
first = down;
}
if (index == size-1){
last = up;
}
size--;
}
}
public Node getNode(int index) {
Node temp = null;
if (index <= (size >> 1)) {
temp = first;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
} else {
temp = last;
for (int i = size - 1; i > index; i--) {
temp = temp.previous;
}
return temp;
}
return temp;
}
public Object get(int index){
checkRange(index);
Node temp = getNode(index);
return temp!=null?temp.element:null;
}
private void checkRange(int index){
if (index<0||index>size-1){
throw new RuntimeException("索引数字不合法"+index);
}
}
public void add(E obj){
Node node = new Node(obj);
if (first==null){
first = node;
last = node;
}else {
node.previous = last;
node.next = null;
last.next = node;
last = node;
}
size++;
}
public String toString(){
StringBuilder sb = new StringBuilder("[");
Node temp = first;
while (temp!=null){
sb.append(temp.element+",");
// System.out.println(temp.element);
temp=temp.next;
}
sb.setCharAt(sb.length()-1,']');
return sb.toString();
}
public static void main(String[] args) {
LinkList<String> list = new LinkList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
System.out.println(list.toString());
System.out.println(list.get(2));
list.remove(0);
list.insert(3,"yhq");
System.out.println(list);
}
}
Map接口
Map就是用来存储“健(key)-值(value)对”的。Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。
public class TestMap {
public static void main(String[] args) {
Map<String,Integer> m1 = new HashMap<>();
m1.put("one",1);
m1.put("tow",2);
m1.put("three",3);
m1.put("four",4);
System.out.println(m1.get("one"));
}
}
另外,Map中的value也可以为对象:
class Employee{
private int id;
private String ename;
private double salary;
public Employee(int id, String ename, double salary) {
this.id = id;
this.ename = ename;
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", ename='" + ename + '\'' +
", salary=" + salary +
'}';
}
}
public class TestMap {
public static void main(String[] args) {
Employee e1 = new Employee(1001,"yhq",4000);
Employee e2 = new Employee(1002,"lxk",5000);
Employee e3 = new Employee(1003,"lxy",6000);
Map<Integer,Employee> map = new HashMap<>();
map.put(1001,e1);
map.put(1002,e2);
map.put(1003,e3);
System.out.println(map);
}
哈希表
HashMap底层实现采用了哈希表,这是一种非常重要的数据结构。哈希表的基本结构就是“数组+链表”。手动实现HashMap如下:
HashNode.java:
package cn.lxk.mycollection;
public class HashNode<K,V> {
int hash;
K key;
V value;
HashNode next;
}
HashMap.java:
package cn.lxk.mycollection;
import java.util.Arrays;
//自定义HashMap
public class HashMap<K,V> {
HashNode[] table; //位桶数组
int size;
public HashMap(){
table = new HashNode[16];
}
public void put(K key,V value){
//还需要考虑数组扩容的问F题
HashNode newNode = new HashNode();
newNode.hash = myHash(key.hashCode(),table.length);
System.out.println("Hash Code"+key.hashCode());
newNode.key = key;
newNode.value = value;
newNode.next = null;
HashNode temp = table[newNode.hash];
HashNode iterLast = null; //正在遍历的最后一个元素
//若此处数组元素为空,则直接放新节点进去
boolean keyRepeat = false;
if (temp==null){
table[newNode.hash] = newNode;
size++;
}else {
//此处数组元素不为空,则遍历对应链表
while (temp!=null){
//判断key如果重复,则覆盖
if (temp.key.equals(key)){
keyRepeat = true;
temp.value = value;//覆盖value即可,其他不变
System.out.println("key重复了");
break;
}else {
//key不重复,则遍历下一个
iterLast = temp;
temp = temp.next;
}
}
if (!keyRepeat){
iterLast.next = newNode;
size++;
}
}
}
public int myHash(int v,int length){
System.out.println("哈希值:"+(v&(length -1)));
return v&(length -1); //求余
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
//遍历bucket数组
for (int i = 0;i<table.length;i++){
HashNode temp = table[i];
//遍历链表
while (temp!=null){
sb.append(temp.key+":"+temp.value+",");
temp = temp.next;
}
}
sb.setCharAt(sb.length()-1,'}');
return sb.toString();
}
public V get(K key){
int hash = myHash(key.hashCode(), table.length);
V value = null;
if (table[hash]!=null){
HashNode temp = table[hash];
while (temp!=null){
if (temp.key.equals(key)){//如果相等,则说明找到了键值对,返回相应的value
value = (V)temp.value;
break;
}else {
temp = temp.next;
}
}
}
return value;
}
public static void main(String[] args) {
HashMap<Integer,String> m = new HashMap<>();
m.put(10,"aa");
m.put(53,"bb");//hash值是5
m.put(12,"cc");
m.put(13,"dd");
m.put(69,"sssss");//hash值是5
m.put(85,"yhq"); //hash值是5
System.out.println(m.get(69));
}
}
迭代器
迭代器是遍历collection的一种工具。
package cn.lxk.mycollection;
import java.util.*;
import java.util.HashMap;
public class TestIterator {
public static void main(String[] args) {
testIteratorMap();
}
public static void testIteratorList(){
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
//使用迭代器遍历list,相当于提供一个专业的接口来遍历容器
for (Iterator<String >iter = list.iterator();iter.hasNext();){
//(获得迭代器;判断有没有下一个)
String temp = iter.next(); //返回元素
System.out.println(temp);
}
}
public static void testIteratorMap(){
Map<Integer,String>map1 = new HashMap<>();
//第一种遍历Map的方式
Set<Map.Entry<Integer,String>> ss = map1.entrySet(); //Map.Entry<Integer,String>相当于一个键值对类型
for (Iterator<Map.Entry<Integer,String>>iter = ss.iterator();iter.hasNext();){
Map.Entry<Integer,String> temp = iter.next();
System.out.println(temp.getKey()+"---"+temp.getValue());
}
//第二种遍历Map的方式
Set<Integer> keySet = map1.keySet();
for (Iterator<Integer>iter=keySet.iterator();iter.hasNext();){
Integer key = iter.next();
System.out.println(key+"----"+map1.get(key));
}
}
}
使用while来遍历:
Iterator iter = list.iterator();
while(iter.hasNext()){
Object obj = iter.next();
iter.remove();//按条件删除时,也建议使用此种方式
}
JavaBean
JavaBean 是一种JAVA语言写成的****可重用组件****。为写成JavaBean,类必须是****具体的和公共的*,并且具有****无参数的**构造器*。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,****set和get方法获取****。
public class TestStoreData {
public static void main(String[] args) {
User user1 = new User(1001,"张三",2000,"2018.9.10");
List<User>list = new ArrayList<>();
list.add(user1);
for (User u:list){
System.out.println(u);
}
Map<Integer,User>map = new HashMap<>();
Set<Integer>keyset = map.keySet();
map.put(1,user1);
for (Integer key:keyset){
System.out.println(key+"===="+map.get(key));
}
}
}
class User{
private int id;
private String name;
private double salary;
private String hiredate;
public User(){//一个完整的javabean。要有set和get方法,以及无参构造器
}
public User(int id, String name, double salary, String hiredate) {
this.id = id;
this.name = name;
this.salary = salary;
this.hiredate = hiredate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getHiredate() {
return hiredate;
}
public void setHiredate(String hiredate) {
this.hiredate = hiredate;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", salary=" + salary +
", hiredate='" + hiredate + '\'' +
'}';
}
}