道德三皇五帝,功名夏后商周。
五霸七雄闹春秋,秦汉兴亡过手。
青史几行名姓,北邙无数荒丘。
前人田地后人收,说甚龙争虎斗
集合框架
从上面的集合框架图可以看到,Java集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection接口又有3种子类型,List、Set和Queue,再下面是一些抽象类,最后是具体实现类,常用的有ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap等等。
从Collection接口开始讲起
Collection接口是处理对象集合的根接口,其中定义了很多对元素进行操作的方法,AbstractCollection是提供Collection部分实现的抽象类。
Collection接口结构
常用的方法有:add()添加一个元素到集合中,addAll()将制定集合中的所有元素添加到集合中,contains()方法检测集合中是否包含指定的元素,toArray()方法返回一个表示集合的数组。
Collections是一个类,容器的工具类,就如同Arrays是数组的工具类
Collection是 Set List Queue和 Deque的接口
Queue: 先进先出队列
Deque: 双向链表
注:Collection和Map之间没有关系,Collection是放一个一个对象的,Map 是放键值对的
注:Deque 继承 Queue,间接的继承了 Collection
Collection的三个子接口
List
它可以定义一个允许重复的有序集合,从List接口中的方法来看,List接口主要是增加了面向位置的操作,允许在指定位置上操作元素,同时增加了一个能够双向遍历线性表的新列表迭代器ListIterator。AbstractList类提供了List接口的部分实现。AbstractSequentialList扩展自AbstractList,主要是提供对链表的支持。下面介绍List接口的两个重要的具体实现类,也是我们可能最常用的类,ArrayList和LinkedList。
最常用的集合框架ArrayList
- 内部数据结构
//用来存放数据元素的数组
transient Object[] elementData;
//当前存储元素的个数
private int size;
- 添加指定元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); //扩容处理
elementData[size++] = e;//添加元素
return true;
}
//此方法主要是确定将要创建的数组大小。
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//确定了添加元素后的大小之后将元素复制到新数组中
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容后的容量增加一半
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 移除指定元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0) // 删除某个元素时需要移动其它数组元素
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; // clear to let GC do its work
}
- 容器类遍历的方法
- 如果没有使用泛型,建议使用迭代器进行遍历
Iterator iterator = h.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); }
- 如果使用了泛型,可以使用增强型for循环或者for循环进行遍历
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。
java hero.name="garen"; hero1.name="ketty"; ArrayList<Hero> heroArrayList = new ArrayList<>(); heroArrayList.add(hero); heroArrayList.add(hero1); for (Hero hh : heroArrayList) { System.out.println(hh.name); } for (int i = 0; i < heroArrayList.size(); i++) { System.out.println(heroArrayList.get(i).name); }
LinkedList
LinkedList同样实现了List接口,LinkedList还实现了双向链表结构Deque
可以很方便的在头尾插入删除数据.
- 源码赏析
transient关键字 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
-数据结构//存储的元素个数 transient int size = 0; //头节点 transient Node<E> first; //尾节点 transient Node<E> last;
- 添加元素
public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null);//有趣 last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
- 删除元素
E unlink(Node<E> x) { final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) {// 当前节点为头节点,重置头节点 first = next; } else {//当前节点非头节点,将前驱节点和后继节点连接 prev.next = next; x.prev = null; } if (next == null) {//当前节点为尾节点,重置尾节点 last = prev; } else {// 当前节点非尾节点 next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
List接口的常用方法
名称 | 作用 |
---|---|
add | 增加一个元素 |
contains | 是否存在一个元素 |
get | 根据下表获取值 |
indexOf | 获取对象所处的位置 |
remove | 删除 |
set | 替换 |
size | 获取大小 |
toArray | 转换为数组 |
addAll | 把另一个容器的对象都加入进来 |
clear | 清空容器 |
Map
对于Map而言,key是唯一的,不可以重复的。
HashMap
安利一篇关于jdk1.8的HashMap详解
HashMap原理:使用数组加链表加红黑树,如果链表长度大于8,则将链表自动转换为红黑树结构,关于红黑树的原理精讲,暂且存着
进行键值映射
HashMap和HashSet都是无序的,具体顺序和JVM有关系
- 和HashTabe的区别
HashMap可以存放null
HashTable不能存放null
HasoMap不是线程安全类
常用方法
HashMap<String,Integer>map = new HashMap<>();
map.put("lihouhua",18);
map.keySet()//获取所有的key
map.values()//获取所有的values
map.get(str)
map.putAll(map)
map.clear();
HashSet
原理,依赖HashMap函数,所有插入的元素作为键,值为final PRESENT
这也是没有重复元素的原因
- LinkedList和TreeSet
HashSet无序
LinkedHashSet按照插入顺序,及不重复又有顺序,天然去重
TreeSet从小到大排序 - 常用的方法
add addall remove
Hashcode原理
所有的对象都有一个对应的hashcode,但并不是说所有的hashcode值肯定不一样,具体原理为hashcode本身是一个native方法
对于hashcode函数来说,有些JVM在实现时是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能存储地址有一定关联。下面是HotSpot JVM中生成hash散列值的实现:
该实现位于hotspot/src/share/vm/runtime/synchronizer.cpp文件下。
static inline intptr_t get_next_hash(Thread * Self, oop obj) {
intptr_t value = 0 ;
if (hashCode == 0) {
// This form uses an unguarded global Park-Miller RNG,
// so it's possible for two threads to race and generate the same RNG.
// On MP system we'll have lots of RW access to a global, so the
// mechanism induces lots of coherency traffic.
value = os::random() ;
} else
if (hashCode == 1) {
// This variation has the property of being stable (idempotent)
// between STW operations. This can be useful in some of the 1-0
// synchronization schemes.
intptr_t addrBits = intptr_t(obj) >> 3 ;
value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
} else
if (hashCode == 2) {
value = 1 ; // for sensitivity testing
} else
if (hashCode == 3) {
value = ++GVars.hcSequence ;
} else
if (hashCode == 4) {
value = intptr_t(obj) ;
} else {
// Marsaglia's xor-shift scheme with thread-specific state
// This is probably the best overall implementation -- we'll
// likely make this the default in future releases.
unsigned t = Self->_hashStateX ;
t ^= (t << 11) ;
Self->_hashStateX = Self->_hashStateY ;
Self->_hashStateY = Self->_hashStateZ ;
Self->_hashStateZ = Self->_hashStateW ;
unsigned v = Self->_hashStateW ;
v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
Self->_hashStateW = v ;
value = v ;
}
value &= markOopDesc::hash_mask;
if (value == 0) value = 0xBAD ;
assert (value != markOopDesc::no_hash, "invariant") ;
TEVENT (hashCode: GENERATE) ;
return value;
}
对于使用到hashcode才能成立的数据结构,我们在使用equals函数之后,如果对于一个使用到hashcode的方法来说的话,我们同时需要对hashcode函数进行重写,不然相关函数会返回Null。
hashcode文章详解
collections类
clolections类是colllections对应的工具类,常用的类方法有
方法 | 简介 |
---|---|
reverse | 反转 |
shuffle | 混淆,顺序乱掉 |
sort | 排序 |
swap | 交换 |
rotate | 滚动 |
synchronizedList | 线程安全化,把非线程安全的类转化为线程安全类 |
泛型
意义
泛型的用法是在容器后面添加Type可以是类,抽象类,接口,泛型表示这种容器,只能存放APHero,ADHero就放不进去了。
可以在一定程度上保证安全。
通配符参数
一般来说? extends Hero作为参数,而不需要直接初始化,
常用的来说,我们传入一个苹果类可以用 ? extends Fruitl
lambada表达式
代替方法参数的表达式,从匿名类转化过来,匿名类
假设一个情景: 找出满足条件的Hero
本教程将从使用普通方法,匿名类,以及Lambda这几种方式,逐渐的引入Lambda的概念
普通方法:
public static int filter(ArrayList<Hero>heroes ){
int count = 0;
Iterator iterator = heroes.iterator();
for (int i = 0; i < heroes.size(); i++) {
if (heroes.get(i).hp>50){
count++;
}
}
return count;
}
匿名类:
首先继承接口,之后实现匿名方法
Hero_count hero_count = new Hero_count() {
@Override
public boolean hero_count(Hero hero) {
if (hero.hp>50)return true;
return false;
}
};
之后调用匿名类
private static int filter(ArrayList<Hero> arrayList, Hero_count hero_count) {
int count=0;
for (Hero h :
arrayList) {
if (hero_count.hero_count(h))count++;
}
return count;
}
Lambda的使用:---一种匿名方法
调用方式相同,传入的参数不同
传入的参数为h->h.hp>50
Hero_count c = h->h.hp>50
private static int filter(ArrayList<Hero> arrayList, Hero_count hero_count) {
int count=0;
for (Hero h :
arrayList) {
if (hero_count.hero_count(h))count++;
}
return count;
}
网络编程
基本概念
- IP:IP地址的作用就是标识一台在网络中的主机。
127.0.0.1表示this也就是本地主机 - 端口 对应相应服务
- 对应异常是UnknowHostException
方法
- 获取本机IP地址
InetAddress host = InetAddress.getLocalHost();
String ip = host.getHostAddress();
如何执行ping命令
Process p = Runtime.getRuntime().exec("ping "+"192。168.2.106");
BufferedReader br - new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();