包含java8排序源码解析的词条

博主:adminadmin 2023-01-22 22:15:09 178

本篇文章给大家谈谈java8排序源码解析,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

用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排序源码解析的信息别忘了在本站进行查找喔。