GVKun编程网logo

为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?(enum为什么是单例)

11

本文将为您提供关于为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?的详细介绍,我们还将为您解释enum为什么是单例的相关知识,同时,我们还将为您提供关于202

本文将为您提供关于为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?的详细介绍,我们还将为您解释enum为什么是单例的相关知识,同时,我们还将为您提供关于2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。你可以假设所有输入数组都可以、Enum 和 MaterialEnum 有什么区别?、Enum.values()与EnumSet.allOf()。哪一个更可取?、Enum.values()与EnumSet.allOf()哪一个更可取?的实用信息。

本文目录一览:

为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?(enum为什么是单例)

为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?(enum为什么是单例)

以下是EnumMap的Java文档的
实现注释”
部分的内容:

实施注意事项:所有基本操作均按固定时间执行。它们可能(尽管不能保证)比其HashMap同行更快。

我在java doc中EnumSet也看到了类似的内容。我想知道为什么它比散列的同行更有可能EnumSets而且EnumMaps会更快?

答案1

小编典典

EnumSet由位数组支持。由于您可以EnumSet预先输入不同项目的数量,因此我们可以简单地为每个枚举值保留一位。您可以想象对Set<Byte>或进行类似的优化Set<Short>,但是对于Set<Integer>(通常需要0.5
GiB的内存来存储2 ^ 32位)或一般而言,这是不可行的。

因此,基本操作就像exists或设置了add恒定时间(就像HashSet),但是它们只需要检查或设置一位。没有hashCode()计算。这就是为什么EnumSet更快。还有更复杂的操作(例如并集)或使用位操作技术轻松实现的操作。

在OpenJDK的有两种实现方式EnumSetRegularEnumSet能够处理多达64个值枚举在longJumboEnumSet更大的枚举(使用long[])。但这只是实现细节。

EnumMap按照类似的原理工作,但是它用于Object[]存储值,而从中隐式地推断了键(索引)Enum.ordinal()

2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。你可以假设所有输入数组都可以

2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。你可以假设所有输入数组都可以

2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。你可以假设所有输入数组都可以得到满足题目要求的结果。力扣324。

福大大 答案2021-11-05:

需要了解快排和完美洗牌问题。
时间复杂度:O(N)。
空间复杂度:O(1)。

代码用golang编写。代码如下:

package main

import (
    "fmt"
    "math/rand"
)

func main() {
   
    nums := []int{
   1, 5, 1, 1, 6, 4}
    wiggleSort(nums)
    fmt.Println(nums)
}

// 时间复杂度O(N),额外空间复杂度O(1)
func wiggleSort(nums []int) {
   
    if len(nums) < 2 {
   
        return
    }
    N := len(nums)
    // 小 中 右
    findIndexNum(nums, 0, len(nums)-1, N/2)
    if (N & 1) == 0 {
   
        // R L -> L R
        shuffle(nums, 0, len(nums)-1)
        // R1 L1 R2 L2 R3 L3 R4 L4
        // L4 R4 L3 R3 L2 R2 L1 R1 -> 代码中的方式,可以的!
        // L1 R1 L2 R2 L3 R3 L4 R4 -> 课上的分析,是不行的!不能两两交换!
        reverse(nums, 0, len(nums)-1)
        // 做个实验,如果把上一行的code注释掉(reverse过程),然后跑下面注释掉的for循环代码
        // for循环的代码就是两两交换,会发现对数器报错,说明两两交换是不行的, 必须整体逆序
        // for (int i = 0; i < nums.length; i += 2) {
   
        // swap(nums, i, i + 1);
        // }
    } else {
   
        shuffle(nums, 1, len(nums)-1)
    }
}

func findIndexNum(arr []int, L int, R int, index int) int {
   
    pivot := 0
    var range2 []int
    for L < R {
   
        //pivot = arr[L+(int)(Math.random()*(R-L+1))]
        pivot = arr[L+rand.Intn(R-L+1)]
        range2 = partition(arr, L, R, pivot)
        if index >= range2[0] && index <= range2[1] {
   
            return arr[index]
        } else if index < range2[0] {
   
            R = range2[0] - 1
        } else {
   
            L = range2[1] + 1
        }
    }
    return arr[L]
}

func partition(arr []int, L int, R int, pivot int) []int {
   
    less := L - 1
    more := R + 1
    cur := L
    for cur < more {
   
        if arr[cur] < pivot {
   
            less++
            //swap(arr, ++less, cur++);
            arr[less], arr[cur] = arr[cur], arr[less]
            cur++
        } else if arr[cur] > pivot {
   
            more--
            //swap(arr, cur, --more);
            arr[more], arr[cur] = arr[cur], arr[more]
        } else {
   
            cur++
        }
    }
    return []int{
   less + 1, more - 1}
}

func shuffle(nums []int, l int, r int) {
   
    for r-l+1 > 0 {
   
        lenAndOne := r - l + 2
        bloom := 3
        k := 1
        for bloom <= lenAndOne/3 {
   
            bloom *= 3
            k++
        }
        m := (bloom - 1) / 2
        mid := (l + r) / 2
        rotate(nums, l+m, mid, mid+m)
        cycles(nums, l-1, bloom, k)
        l = l + bloom - 1
    }
}

func cycles(nums []int, base int, bloom int, k int) {
   
    for i, trigger := 0, 1; i < k; i, trigger = i+1, trigger*3 {
   
        next := (2 * trigger) % bloom
        cur := next
        record := nums[next+base]
        tmp := 0
        nums[next+base] = nums[trigger+base]
        for cur != trigger {
   
            next = (2 * cur) % bloom
            tmp = nums[next+base]
            nums[next+base] = record
            cur = next
            record = tmp
        }
    }
}

func rotate(arr []int, l int, m int, r int) {
   
    reverse(arr, l, m)
    reverse(arr, m+1, r)
    reverse(arr, l, r)
}

func reverse(arr []int, l int, r int) {
   
    for l < r {
   
        arr[l], arr[r] = arr[r], arr[l]
        l++
        r--
    }
}

执行结果如下:
图片


左神java代码

Enum 和 MaterialEnum 有什么区别?

Enum 和 MaterialEnum 有什么区别?

tl;dr:它们确实只是同义词!


查看相应的抽屉类 MaterialPropertyDrawer source code 实际上它在内部称为 MaterialEnumDrawer

但是在 GetShaderPropertyDrawer 中,当他们搜索给定属性 they do

的抽屉实现时
...

// When you write [Foo] in shader,get Foo,FooDrawer,MaterialFooDrawer,// FooDecorator or MaterialFooDecorator class;
// "kind of" similar to how C# does attributes.

if (klass.Name == className ||
    klass.Name == className + "Drawer" ||
    klass.Name == "Material" + className + "Drawer" ||
    klass.Name == className + "Decorator" ||
    klass.Name == "Material" + className + "Decorator")
{

...

因此,正如您所看到的,无论您是否使用 Material 编写它基本上都没有关系,它们基本上被视为同义词:

  • 对于 [Enum],您会得到 EnumEnumDrawerMaterialEnumDrawerEnumDecoratorMaterialEnumDecorator
  • 对于 [MaterialEnum],您会得到 MaterialEnumMaterialEnumDrawerMaterialMaterialEnumDrawerMaterialEnumDecoratorMaterialMaterialEnumDecorator

=>您实际要找的那个MaterialEnumDrawer在两个版本中都能找到。

所以基本上你可以把它写成以下之一

Enum
MaterialEnum
MaterialEnumDrawer

Fazit:使用[Enum]

  • 它更短;)
  • 其他人可以在 API 中找到它

Enum.values()与EnumSet.allOf()。哪一个更可取?

Enum.values()与EnumSet.allOf()。哪一个更可取?

我仔细研究了EnumSet.allOf它,它看起来非常高效,尤其是对于值小于64的枚举。

基本上,所有集合共享所有可能的枚举值的单个数组,而唯一的另一条信息是位掩码,如果allOf设置为一,则将其设置为。

另一方面,Enum.values()似乎有点黑魔法。此外,它返回一个数组,而不是一个集合,因此在许多情况下,必须用Arrays.asList()装饰它,以便在任何需要集合的地方使用。

那么,应该EnumSet.allOf更可取Enum.values吗?

更具体地说,for应使用哪种形式的迭代器:

for ( final MyEnum val: MyEnum.values( ) );

要么

for ( final MyEnum val: EnumSet.allOf( MyEnum.class ) );

Enum.values()与EnumSet.allOf()哪一个更可取?

Enum.values()与EnumSet.allOf()哪一个更可取?

我仔细研究了EnumSet.allOf它,它看起来非常高效,尤其是对于值小于64的枚举。

基本上,所有集合共享所有可能的枚举值的单个数组,而唯一的另一条信息是位掩码,如果allOf设置为一,则将其设置为。

另一方面,Enum.values()似乎有点黑魔法。此外,它返回一个数组,而不是一个集合,因此在许多情况下,必须用Arrays.asList()装饰它,以便在任何需要集合的地方使用。

那么,应该EnumSet.allOf更可取Enum.values吗?

更具体地说,for应使用哪种形式的迭代器:

for ( final MyEnum val: MyEnum.values( ) );

要么

for ( final MyEnum val: EnumSet.allOf( MyEnum.class ) );

今天关于为什么EnumSet或EnumMap的性能可能比散列的EnumSet或EnumMap更好?enum为什么是单例的讲解已经结束,谢谢您的阅读,如果想了解更多关于2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。你可以假设所有输入数组都可以、Enum 和 MaterialEnum 有什么区别?、Enum.values()与EnumSet.allOf()。哪一个更可取?、Enum.values()与EnumSet.allOf()哪一个更可取?的相关知识,请在本站搜索。

本文标签: