包含java8排序源码解析的词条
本篇文章给大家谈谈java8排序源码解析,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、用JAVA语言实现对数组[8,15,7,669,25,4,32]的非递减排序,求程序源代码及运行结果
- 2、源码解析-偏向锁撤销流程解读
- 3、java7和java8对hashmap做了哪些优化
- 4、求JAVA冒泡排序法的代码
- 5、关于Java中Array.sort()排序原理,越详细越好!
用JAVA语言实现对数组[8,15,7,669,25,4,32]的非递减排序,求程序源代码及运行结果
public static void sort(int[] num){
for (int i =0;inum.length-1;i++)
for(int j=i+1;jnum.length;j++){
if (num[i]num[j]){
tmp = num[i];
num[i] =num[j];
num[j]=tmp;
}
}
}
源码解析-偏向锁撤销流程解读
源码链接:
简单总结下偏向撤销的流程:
细节补充:
如何判断偏向所有者没有正在持有该偏向锁?
分两步,首先判断偏向所有者是否还活着,如果还活着,则遍历它的栈,看是否能找到关联该锁的锁记录,如果找到,则正在持有,如果没找到,则没有持有。(遍历过程在一个安全点执行,此时偏向所有者被阻塞。)
偏向所有者正在持有该偏向锁,如何将其撤销为轻量级锁?
遍历偏向所有者的栈,修改与该锁关联的所有锁记录,让偏向所有者以为它对该对象加的就是轻量级锁。
源码中的 highest_lock,为什么说是最早关联偏向锁的锁记录呢?
首先,锁记录在栈里是连续存放的。
请求获取锁时,按照从低地址到高地址的顺序,找在已关联该锁的锁记录之前,最后一个空闲的锁记录(没有指向任何锁对象)。
请求锁的源码如下:
而撤销偏向锁时,遍历偏向所有者的锁记录,也是按照从低地址到高地址的顺序,但它没有 break 的逻辑,因为它要处理所有关联该锁的锁记录。所以退出循环后,highest_lock 指向的是最早关联该锁的锁记录。
这篇: 源码解析-触发批量撤销或批量重偏向的条件 ,介绍了批量撤销的触发条件。
包含批量撤销逻辑的源码:
禁用类的可偏向属性有两点作用:
对于批量撤销时,正在被线程持有的偏向锁,通过在安全点遍历所有 Java 线程的栈,将偏向锁撤销为轻量级锁。
java7和java8对hashmap做了哪些优化
HashMap的原理介绍
此乃老生常谈,不作仔细解说。
一句话概括之:HashMap是一个散列表,它存储的内容是键值对(key-value)映射。
Java 7 中HashMap的源码分析
首先是HashMap的构造函数代码块1中,根据初始化的Capacity与loadFactor(加载因子)初始化HashMap.
//代码块1
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor = 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
Java7中对于key1,value1的put方法实现相对比较简单,首先根据 key1 的key值计算hash值,再根据该hash值与table的length确定该key所在的index,如果当前位置的Entry不为null,则在该Entry链中遍历,如果找到hash值和key值都相同,则将值value覆盖,返回oldValue;如果当前位置的Entry为null,则直接addEntry。
代码块2
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (EntryK,V e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
//addEntry方法中会检查当前table是否需要resize
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size = threshold) (null != table[bucketIndex])) {
resize(2 * table.length); //当前map中的size 如果大于threshole的阈值,则将resize将table的length扩大2倍。
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
Java7 中resize()方法的实现比较简单,将OldTable的长度扩展,并且将oldTable中的Entry根据rehash的标记重新计算hash值和index移动到newTable中去。代码如代码块3中所示,
//代码块3 --JDK7中HashMap.resize()方法
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable, initHashSeedAsNeeded(newCapacity));
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
/**
* 将当前table的Entry转移到新的table中
*/
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (EntryK,V e : table) {
while(null != e) {
EntryK,V next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
HashMap性能的有两个参数:初始容量(initialCapacity) 和加载因子(loadFactor)。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
根据源码分析可以看出:在Java7 中 HashMap的entry是按照index索引存储的,遇到hash冲突的时候采用拉链法解决冲突,将冲突的key和value插入到链表list中。
然而这种解决方法会有一个缺点,假如key值都冲突,HashMap会退化成一个链表,get的复杂度会变成O(n)。
在Java8中为了优化该最坏情况下的性能,采用了平衡树来存放这些hash冲突的键值对,性能由此可以提升至O(logn)。
代码块4 -- JDK8中HashMap中常量定义
static final int DEFAULT_INITIAL_CAPACITY = 1 4;
static final int TREEIFY_THRESHOLD = 8; // 是否将list转换成tree的阈值
static final int UNTREEIFY_THRESHOLD = 6; // 在resize操作中,决定是否untreeify的阈值
static final int MIN_TREEIFY_CAPACITY = 64; // 决定是否转换成tree的最小容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; // default的加载因子
在Java 8 HashMap的put方法实现如代码块5所示,
代码块5 --JDK8 HashMap.put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
NodeK,V[] tab; NodeK,V p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length; //table为空的时候,n为table的长度
if ((p = tab[i = (n - 1) hash]) == null)
tab[i] = newNode(hash, key, value, null); // (n - 1) hash 与Java7中indexFor方法的实现相同,若i位置上的值为空,则新建一个Node,table[i]指向该Node。
else {
// 若i位置上的值不为空,判断当前位置上的Node p 是否与要插入的key的hash和key相同
NodeK,V e; K k;
if (p.hash == hash
((k = p.key) == key || (key != null key.equals(k))))
e = p;//相同则覆盖之
else if (p instanceof TreeNode)
// 不同,且当前位置上的的node p已经是TreeNode的实例,则再该树上插入新的node。
e = ((TreeNodeK,V)p).putTreeVal(this, tab, hash, key, value);
else {
// 在i位置上的链表中找到p.next为null的位置,binCount计算出当前链表的长度,如果继续将冲突的节点插入到该链表中,会使链表的长度大于tree化的阈值,则将链表转换成tree。
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount = TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash
((k = e.key) == key || (key != null key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size threshold)
resize();
afterNodeInsertion(evict);
return null;
}
再看下resize方法,由于需要考虑hash冲突解决时采用的可能是list 也可能是balance tree的方式,因此resize方法相比JDK7中复杂了一些,
代码块6 -- JDK8的resize方法
inal NodeK,V[] resize() {
NodeK,V[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap 0) {
if (oldCap = MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;//如果超过最大容量,无法再扩充table
return oldTab;
}
else if ((newCap = oldCap 1) MAXIMUM_CAPACITY
oldCap = DEFAULT_INITIAL_CAPACITY)
newThr = oldThr 1; // threshold门槛扩大至2倍
}
else if (oldThr 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap MAXIMUM_CAPACITY ft (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
NodeK,V[] newTab = (NodeK,V[])new Node[newCap];// 创建容量为newCap的newTab,并将oldTab中的Node迁移过来,这里需要考虑链表和tree两种情况。
求JAVA冒泡排序法的代码
你好!很高兴能帮到你。
由于你刚学Java,所以一些编程规范是需要注意的,而我提供给你的答案看起来虽然有点复杂,不过采用了面向对象的编程思想,尽量做到低耦合高内聚,同时冒泡算法也做了升级,为冒泡的高级快速排序算法,不过为了对比,也保存了传统的冒泡算法。
需要讲解一下,算法本身不难,难在如何做到编程规范、以及方便修改、易于修改、使得程序灵活、低耦合高内聚。
算法部分请看Bubble类,里面有两种算法,有注释。
主类为TestBubble,主要用于调用Bubble对象运行算法、StuInfo对象提供学生作者信息、Info对象提供运行过程中提示信息。
运行结果如下(Bubble类为核心算法类):
************************************
run:
请输入您将要输入整数的个数:
10
请输入一串数字进行冒泡排序,注意:每次只输入一个,输完则回车
1:10
2:23
3:11
4:56
5:45
6:26
7:59
8:28
9:84
10:79
初始序列的数组为:
10 23 11 56 45 26 59 28 84 79
学号:200815009* 班级:08软件3班 姓名:叶科良
排序好的数组为:
10 11 23 26 28 45 56 59 79 84
源代码如下:
***************************************************
package testBubble;
import java.io.Reader;
import java.util.Scanner;
/**
*
* @author yekeliang
*/
public class TestBubble {
private CommandLineBubbleRunner commandLineBubbleRunner;
private int arraySize;
private int[] intArray;
private StuInfo stuInfo;
private Info info;
/**
* 测试方法
* @param args
*/
public static void main(String[] args) {
TestBubble test = new TestBubble();
}
/**
* 构造方法
* 调用初始化学生数据、接收命令行整数、展示结果3个成员方法
*/
public TestBubble() {
initMemb();
initData();
runBubble();
showResult(this.getIntArray());
}
/**
* 初始化学生数据
*/
private void initData() {
stuInfo.setStuNum("200815009*");
stuInfo.setStuClass("08软件3班");
stuInfo.setStuName("叶科良");
info.setInputIntNumInfo("请输入您将要输入整数的个数:");
info.setInputIntInfo("请输入一串数字进行冒泡排序,注意:每次只输入一个,输完则回车");
info.setShowInputInfo("初始序列的数组为:");
info.setShowResultInfo("排序好的数组为:");
info.setInputErrorInfo("对不起,输入有误!请输入整数.");
}
/**
* 接收命令行整数,使用冒泡算法
*/
private void runBubble() {
try{
System.out.println(info.getInputIntNumInfo());
setArraySize(getCommandLineBubbleRunner().getArraySize());
System.out.println(info.getInputIntInfo());
setIntArray(getCommandLineBubbleRunner().getAcceptAsIntArray(getArraySize()));
System.out.println(info.getShowInputInfo());
getCommandLineBubbleRunner().showAcceptAsIntArray(getIntArray());
Bubble.quick(getIntArray());
} catch(java.util.InputMismatchException e) {
System.out.println(info.getInputErrorInfo());
}
}
/**
* 展示结果
*/
private void showResult(int intArray[]) {
System.out.println("\n" + stuInfo.toString());
System.out.println(info.getShowResultInfo());
for (int i = 0; i intArray.length; i++) {
System.out.print(intArray[i] + " ");
}
}
private void initMemb() {
stuInfo = new StuInfo();
info = new Info();
commandLineBubbleRunner = new CommandLineBubbleRunner();
}
public CommandLineBubbleRunner getCommandLineBubbleRunner() {
return commandLineBubbleRunner;
}
public void setCommandLineBubbleRunner(CommandLineBubbleRunner commandLineBubbleRunner) {
this.commandLineBubbleRunner = commandLineBubbleRunner;
}
public int getArraySize() {
return arraySize;
}
public void setArraySize(int arraySize) {
this.arraySize = arraySize;
}
public int[] getIntArray() {
return intArray;
}
public void setIntArray(int[] intArray) {
this.intArray = intArray;
}
private void getStuInfo() {}
}
/**
*
* @author 叶科良
*/
class CommandLineBubbleRunner {
public int num;//输入整数个数
/**
* 从命令行中读取需要输入的整数个数
* @return 需要输入的整数个数
*/
public int getArraySize() {
Scanner reader1 = new Scanner(System.in);
num = reader1.nextInt();
return num;
}
/**
* 指定数组大小,从命令行接收整数
* @param arraySize 数组大小
* @return 原始整数数组
*/
public int[] getAcceptAsIntArray(int arraySize) {
int[] acceptArray = new int[arraySize];
Scanner reader = new Scanner(System.in);
for (int i = 0; i getNum(); i++) {
System.out.print((i + 1) + ":");
acceptArray[i] = reader.nextInt();
}
return acceptArray;
}
/**
* 打印原始输入数据
* @param intArray
*/
public void showAcceptAsIntArray(int[] intArray){
for (int i = 0; i getNum(); i++) {
System.out.print(intArray[i] + " ");
}
}
/**
* 取得数组大小
* @return
*/
public int getNum() {
return num;
}
}
class Bubble {
/**
* 给定一个数组,使用冒泡算法进行排序
* @param acceptArray 给定的一个数组
* @return 排序好的数组
*/
public static int[] getResultAsIntArray(int[] acceptArray) {
int i, temp;
for (i = 0; i (acceptArray.length - 1); i++) {//两两进行比较,符合条件的进行交换
if (acceptArray[i] acceptArray[i + 1]) {
temp = acceptArray[i];
acceptArray[i] = acceptArray[i + 1];
acceptArray[i + 1] = temp;
}
}
return acceptArray;
}
/**
* 快速冒泡排序算法
* @param r 输入的整数数组
* @param first 数组第一个下标
* @param end 数组最后一个下标
* @return 排好序的整数数组
*/
public static int partition(int[] r, int first, int end) {
int i, j;
i = first;
j = end;
while (i j) {
while (i j r[i] = r[j]) {
j--;
}
if (i j) {
int temp;
temp = r[i];
r[i] = r[j];
r[j] = temp;
}
}
return i;
}
public static void quick(int[] r, int first, int end) { //利用递归反复划分
if (first end) {
int pivot = partition(r, first, end); //调用划分函数
quick(r, first, pivot - 1);
quick(r, pivot + 1, end);
}
}
public static int[] quick(int[] r){
quick(r,0,r.length-1);
return r;
}
}
class Info {
private String inputIntNumInfo;//提示用户输入整数个数的消息语句
private String inputIntInfo;//提示用户输入整数的消息语句
private String showInputInfo;//提示显示用户输入整数的消息语句
private String inputErrorInfo;//提示用户输入有误消息语句
private String showResultInfo;//提示显示排序结果
public String getInputIntNumInfo() {
return inputIntNumInfo;
}
public void setInputIntNumInfo(String inputIntNumInfo) {
this.inputIntNumInfo = inputIntNumInfo;
}
public String getInputIntInfo() {
return inputIntInfo;
}
public void setInputIntInfo(String inputIntInfo) {
this.inputIntInfo = inputIntInfo;
}
public String getShowInputInfo() {
return showInputInfo;
}
public void setShowInputInfo(String showInputInfo) {
this.showInputInfo = showInputInfo;
}
public String getInputErrorInfo() {
return inputErrorInfo;
}
public void setInputErrorInfo(String inputErrorInfo) {
this.inputErrorInfo = inputErrorInfo;
}
public String getShowResultInfo() {
return showResultInfo;
}
public void setShowResultInfo(String showResultInfo) {
this.showResultInfo = showResultInfo;
}
}
class StuInfo {
private String stuNum;//学生学号
private String stuName;//学生姓名
private String stuClass;//学生班级
@Override
public String toString() {
return "学号:" + getStuNum() + " 班级:" + getStuClass() + " 姓名:" + getStuName();
}
public String getStuNum() {
return stuNum;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuClass() {
return stuClass;
}
public void setStuClass(String stuClass) {
this.stuClass = stuClass;
}
}
关于Java中Array.sort()排序原理,越详细越好!
是 Arrays.sort(a); 吧
给你看源码
=============
/* */ public static void sort(int[] paramArrayOfInt)
/* */ {
/* 96 */ sort1(paramArrayOfInt, 0, paramArrayOfInt.length);
/* */ }
//
/* */ private static void sort1(int[] paramArrayOfInt, int paramInt1, int paramInt2)
/* */ {
/* 558 */ if (paramInt2 7) {
/* 559 */ for (i = paramInt1; i paramInt2 + paramInt1; i++)
/* 560 */ for (j = i; (j paramInt1) (paramArrayOfInt[(j - 1)] paramArrayOfInt[j]); j--)
/* 561 */ swap(paramArrayOfInt, j, j - 1);
/* 562 */ return;
/* */ }
/* */
/* */
/* 566 */ int i = paramInt1 + (paramInt2 1);
/* 567 */ if (paramInt2 7) {
/* 568 */ j = paramInt1;
/* 569 */ k = paramInt1 + paramInt2 - 1;
/* 570 */ if (paramInt2 40) {
/* 571 */ m = paramInt2 / 8;
/* 572 */ j = med3(paramArrayOfInt, j, j + m, j + 2 * m);
/* 573 */ i = med3(paramArrayOfInt, i - m, i, i + m);
/* 574 */ k = med3(paramArrayOfInt, k - 2 * m, k - m, k);
/* */ }
/* 576 */ i = med3(paramArrayOfInt, j, i, k);
/* */ }
/* 578 */ int j = paramArrayOfInt[i];
/* */
/* */
/* 581 */ int k = paramInt1;int m = k;int n = paramInt1 + paramInt2 - 1;int i1 = n;
/* */ for (;;) {
/* 583 */ if ((m = n) (paramArrayOfInt[m] = j)) {
/* 584 */ if (paramArrayOfInt[m] == j)
/* 585 */ swap(paramArrayOfInt, k++, m);
/* 586 */ m++;
/* */ } else {
/* 588 */ while ((n = m) (paramArrayOfInt[n] = j)) {
/* 589 */ if (paramArrayOfInt[n] == j)
/* 590 */ swap(paramArrayOfInt, n, i1--);
/* 591 */ n--;
/* */ }
/* 593 */ if (m n)
/* */ break;
/* 595 */ swap(paramArrayOfInt, m++, n--);
/* */ }
/* */ }
/* */
/* 599 */ int i3 = paramInt1 + paramInt2;
/* 600 */ int i2 = Math.min(k - paramInt1, m - k);vecswap(paramArrayOfInt, paramInt1, m - i2, i2);
/* 601 */ i2 = Math.min(i1 - n, i3 - i1 - 1);vecswap(paramArrayOfInt, m, i3 - i2, i2);
/* */
/* */
/* 604 */ if ((i2 = m - k) 1)
/* 605 */ sort1(paramArrayOfInt, paramInt1, i2);
/* 606 */ if ((i2 = i1 - n) 1) {
/* 607 */ sort1(paramArrayOfInt, i3 - i2, i2);
/* */ }
/* */ }
/* */
/* */
/* */ private static void swap(int[] paramArrayOfInt, int paramInt1, int paramInt2)
/* */ {
/* 614 */ int i = paramArrayOfInt[paramInt1];
/* 615 */ paramArrayOfInt[paramInt1] = paramArrayOfInt[paramInt2];
/* 616 */ paramArrayOfInt[paramInt2] = i;
/* */ }
java8排序源码解析的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、java8排序源码解析的信息别忘了在本站进行查找喔。