好吧,这个问题几乎说明了一切.使用JPARepository如何更新实体?
JPARepository只有一个save方法,它不会告诉我它是否实际创建或更新.例如,我将一个简单的Object插入数据库User,它有三个字段:firstname和lastname以及age:
@Entity
public class User {
private String firstname;
private String lastname;
//Setters and getters for age omitted, but they are the same as with firstname and lastname.
private int age;
@Column
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
@Column
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
private long userId;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getUserId(){
return this.userId;
}
public …Run Code Online (Sandbox Code Playgroud) 我有一个微基准测试,显示非常奇怪的结果:
@BenchmarkMode(Mode.Throughput)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000)
@Measurement(iterations = 40, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000)
public class Chaining {
private String a1 = "111111111111111111111111";
private String a2 = "222222222222222222222222";
private String a3 = "333333333333333333333333";
@Benchmark
public String typicalChaining() {
return new StringBuilder().append(a1).append(a2).append(a3).toString();
}
@Benchmark
public String noChaining() {
StringBuilder sb = new StringBuilder();
sb.append(a1);
sb.append(a2);
sb.append(a3);
return sb.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
我期待两个测试的结果相同或至少非常接近.但是,差异几乎是5倍:
# Run complete. Total time: 00:01:41 …Run Code Online (Sandbox Code Playgroud) 我在这里看到很多线程比较并尝试回答哪个更快:newInstance或者new operator.
看看源代码,它看起来newInstance应该慢得多,我的意思是它做了很多安全检查并使用反射.而且我决定先测量一下jdk-8.这是使用的代码jmh.
@BenchmarkMode(value = { Mode.AverageTime, Mode.SingleShotTime })
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class TestNewObject {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder().include(TestNewObject.class.getSimpleName()).build();
new Runner(opt).run();
}
@Fork(1)
@Benchmark
public Something newOperator() {
return new Something();
}
@SuppressWarnings("deprecation")
@Fork(1)
@Benchmark
public Something newInstance() throws InstantiationException, IllegalAccessException {
return Something.class.newInstance(); …Run Code Online (Sandbox Code Playgroud) A HashMap有一个来自它的文档的短语:
如果初始容量大于最大条目数除以加载因子,则不会发生重新加载操作.
注意文档怎么说的老调重弹,没有调整 -即使翻版只会当调整大小会发生; 那就是当桶的内部大小增加两倍时.
当然HashMap,我们可以提供这样一个构造函数来定义这个初始容量.
使用指定的初始容量和默认加载因子(0.75)构造一个空的HashMap.
好的,似乎很容易:
// these are NOT chosen randomly...
List<String> list = List.of("DFHXR", "YSXFJ", "TUDDY",
"AXVUH", "RUTWZ", "DEDUC", "WFCVW", "ZETCU", "GCVUR");
int maxNumberOfEntries = list.size(); // 9
double loadFactor = 0.75;
int capacity = (int) (maxNumberOfEntries / loadFactor + 1); // 13
Run Code Online (Sandbox Code Playgroud)
所以容量是13(内部是16- 下一个2的幂),这样我们保证文档部分不重复.好吧,让我们测试一下,但首先介绍一个方法,进入HashMap并查看值:
private static <K, V> void debugResize(Map<K, V> map, K key, V value) throws Throwable …Run Code Online (Sandbox Code Playgroud) 我们刚刚在Amazon Linux上升级到Java 8.我们正在使用Spring 4.3.8.RELEASE.过去我们可以通过在应用程序上下文文件中设置bean来获取我们的机器主机名,就像这样...
<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />
Run Code Online (Sandbox Code Playgroud)
但是对于Java 8,bean"hostname"现在包含字符串
localhost
Run Code Online (Sandbox Code Playgroud)
在Java 8之前,它曾用于包含在命令行上运行的"hostname"值,即
[myuser@machine1 ~]$ hostname
machine1.mydomain.org
Run Code Online (Sandbox Code Playgroud)
如何重新配置我们的bean,以便它获取命令行列出的主机名?我不想在任何地方硬编码.
正如标题所示,这是一个关于实现细节的问题HashMap#resize- 当内部数组的大小加倍时.这有点罗嗦,但我真的试图证明我对此有了最好的理解......
这发生在这个特定桶/箱中的条目以某种方式存储的时刻Linked- 因此具有确切的顺序并且在问题的上下文中这是重要的.
一般来说,resize也可以从其他地方调用,但我们只看这个案例.
假设你将这些字符串作为键放在一个HashMap(右边是hashcode 后面 HashMap#hash - 那是内部重新散列.)是的,这些都是精心生成的,而不是随机的.
DFHXR - 11111
YSXFJ - 01111
TUDDY - 11111
AXVUH - 01111
RUTWZ - 11111
DEDUC - 01111
WFCVW - 11111
ZETCU - 01111
GCVUR - 11111
Run Code Online (Sandbox Code Playgroud)
这里有一个简单的模式 - 最后4位对于所有这些都是相同的 - 这意味着当我们插入这些键中的8个(总共9个)时,它们最终会在同一个桶中; 并在9个HashMap#put时,resize将被调用.
因此,如果当前有8个条目(上面有一个键)HashMap- 这意味着在这个映射中有16个桶,它们的最后4个位决定了条目最终的位置.
我们把第九个键.此时TREEIFY_THRESHOLD被击中并被resize召唤.这些容器加倍,32并且键的另一位决定了该条目的位置(因此,现在为5位).
最终到达这段代码(当resize发生时):
Node<K,V> loHead = null, loTail = null;
Node<K,V> …Run Code Online (Sandbox Code Playgroud) 基本上这是在试图回答另一个问题时出现的.假设这段代码:
AtomicInteger i = new AtomicInteger(0);
AtomicInteger count = new AtomicInteger(0);
IntStream.generate(() -> i.incrementAndGet())
.parallel()
.peek(x -> count.incrementAndGet())
.limit(5)
.forEach(System.out::println);
System.out.println("count = " + count);
Run Code Online (Sandbox Code Playgroud)
我理解这IntStream#generate是一个无序的无限流的事实,并且要完成它必须有一个短路操作(limit在这种情况下).我也明白,在Supplier达到该限制之前,Stream实现的次数可以自由调用.
在java-8下运行它会count一直打印512(可能并不总是,但在我的机器上是这样).
在对比运行中,这在java-10下很少超过5.所以我的问题是内部发生了什么变化,短路发生得更好(我试图通过拥有源并试图做一些差异来解决这个问题......)
假设我有这个简单的方法:
static final Integer me = Integer.parseInt("2");
static int go() {
return me * 2;
}
Run Code Online (Sandbox Code Playgroud)
对于 javac,me不是常量(根据 JLS 规则),但对于 JIT 很可能是。
我试图用以下方法测试:
public class StaticFinal {
public static void main(String[] args) {
int hash = 0;
for(int i=0;i<1000_000;++i){
hash = hash ^ go();
}
System.out.println(hash);
}
static final Integer me = Integer.parseInt("2");
static int go() {
return me * 2;
}
}
Run Code Online (Sandbox Code Playgroud)
并运行它:
java -XX:+UnlockDiagnosticVMOptions
-XX:-TieredCompilation
"-XX:CompileCommand=print,StaticFinal.go"
-XX:PrintAssemblyOptions=intel
StaticFinal.java
Run Code Online (Sandbox Code Playgroud)
我不知道汇编很好,但这很明显:
mov eax,0x4
Run Code Online (Sandbox Code Playgroud)
的结果go立即为4,即:JIT“信任” …
我知道-XmsJVM进程的标志是允许JVM进程使用特定数量的内存来初始化其进程.而对于Java应用程序的性能,通常建议设置为两个相同的价值观-Xms和-Xmx启动应用程序时,喜欢-Xms2048M -Xmx2048M.
我很好奇-Xms和-Xmx标志是否意味着JVM进程预留了特定的内存量以防止同一台机器中的其他进程使用它.
这是正确的吗?
我很难理解java-9中的实现细节ImmutableCollections.SetN; 具体为什么需要两次增加内部数组.
假设你这样做:
Set.of(1,2,3,4) // 4 elements, but internal array is 8
Run Code Online (Sandbox Code Playgroud)
更准确地说,我完全理解为什么这样做(双重扩展)以防万一HashMap- 你从来没有(几乎)想要load_factor成为一个.例如,!=1当条目更好地分散到存储桶时,值可以改善搜索时间.
但是在一个不可变的集合的情况下- 我无法真正说出来.特别是因为选择了内部数组的索引.
让我提供一些细节.首先如何搜索索引:
int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length);
Run Code Online (Sandbox Code Playgroud)
pe是我们放在集合中的实际值.SALT在启动时只生成32位,每次生成一次JVM(如果需要,这是实际的随机化).elements.length我们的例子是8(4个元素,但这里有8个 - 大小加倍).
这个表达式就像一个负安全的模运算.请注意,选择存储桶时HashMap,例如((n - 1) & hash)中会执行相同的逻辑操作.
因此,如果elements.length is 8对于我们的情况,则此表达式将返回任何小于8的正值(0, 1, 2, 3, 4, 5, 6, 7).
现在剩下的方法:
while (true) {
E ee = elements[idx];
if …Run Code Online (Sandbox Code Playgroud)