java中优雅的最小/最大绝对值

java中优雅的最小/最大绝对值,java,Java,在应用绝对值转换后,我需要获取浮点值集合中的最小值和最大值。在python中,我会这样做 min(map(abs, [-5, -7, 10, 2])) 如何以最优雅的方式在java中执行相同的操作?您可能会做一些疯狂的事情,但最简单的解决方案是: List<Integer> x = new ArrayList<Integer>(Arrays.asList( {-5,-7,10,2} } ); for( int i = 0; i < x.size(); i++ ){

在应用绝对值转换后,我需要获取浮点值集合中的最小值和最大值。在python中,我会这样做

min(map(abs, [-5, -7, 10, 2]))

如何以最优雅的方式在java中执行相同的操作?

您可能会做一些疯狂的事情,但最简单的解决方案是:

List<Integer> x = new ArrayList<Integer>(Arrays.asList( {-5,-7,10,2} } );
for( int i = 0; i < x.size(); i++ ){
   x.set( i, Math.abs(x.get(i)) );
}

return Collections.max( x );
List x=newarraylist(Arrays.asList({-5,-7,10,2}});
对于(int i=0;i

和非常有用。

这里有另一种方法。这种方法不需要创建数组的第二个副本,因为
数组。asList
仅生成给定数组的数组备份视图。另一个潜在优势是保留了最小值和最大值的符号。在下面的示例中最小值显示为1.333,最大值显示为-9.43

它比Stefan的解决方案更复杂,但根据具体情况,它可能适合您

    Float numbers[] = {-9.43f, 2.3f, -8.2f, 1.333f};

    // Calculate the minimum
    Float min = Collections.min(Arrays.asList(numbers), 
            new Comparator<Float>() {
                public int compare(Float o1, Float o2) {
                    Float result = Math.abs(o1) - Math.abs(o2);
                    return result > 0 ? 1 : result < 0 ? -1 : 0;
                }
            }
    );

    // Calculate the maximum
    Float max = Collections.min(Arrays.asList(numbers), 
            new Comparator<Float>() {
                public int compare(Float o1, Float o2) {
                    Float result = Math.abs(o2) - Math.abs(o1);
                    return result > 0 ? 1 : result < 0 ? -1 : 0;
                }
            }
    );

    System.out.println("Min = " + min);
    System.out.println("Max = " + max);
编辑:针对评论中的“Hatchtman82”,我决定运行一个简单的基准测试,看看我的解决方案与Stefan Kendall的相比性能如何。对于少于一万个元素的小型阵列,两种解决方案的性能几乎相同。但是,对于较大的阵列,我的解决方案通常性能更好

Stefan的方法非常有效,但它使用的内存大约是我的两倍,因为它必须创建原始数组的副本才能存储每个元素的绝对值。至于时间复杂性,我发现我的方法执行速度快了4到7倍,主要是因为Stefan的方法需要复制arr的时间请记住,这些基准测试是在一台机器上执行的(MacBook Pro、4GB、Core2 Duo@2.53),结果会因计算机和JVM的配置而异

Stefan的方法当然更直截了当,而我的方法在某些情况下可以表现得更好。因此,基本上每种解决方案都是有效的,尽管根据情况,其中一种可能更可取。

在“疯狂的东西”类别中:

import java.util.*;
导入org.apache.commons.collections.iterators.IteratorEnumeration;
导入org.apache.commons.functor.core.collection.transformeditor;
导入org.apache.commons.functor.UnaryFunction;
//...
int commonsMin=Collections.min(
Collections.list((枚举)
新迭代计数法(
新转换器(
asList(3,-5,-7,10,-2,4).iterator(),new-UnaryFunction(){
公共整数求值(整数a)
{
返回Math.abs(a);
}
}))));
//...
如果其中一个Collections.min重载使用了迭代器,或者有一种简单的方法将迭代器转换为集合,那么这真的不会那么疯狂。使用它可能会更明智

编辑:这对于/Google Collections来说更干净。我使用HashSet是因为我们真的不关心顺序:

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

// ...
int guavaMin = Collections.min(
               Sets.newHashSet(
               Iterables.transform(
               Sets.newHashSet(3, -5, -7, 10, -2, 4), new Function<Integer, Integer>(){
                 public Integer apply(Integer a)
                 {
                   return Math.abs(a);
                 }
               })));
// ...
import com.google.common.base.Function;
导入com.google.common.collect.Iterables;
导入com.google.common.collect.set;
// ...
int guavaMin=Collections.min(
Sets.newHashSet(
易变(
newHashSet(3,-5,-7,10,-2,4),new Function(){
公共整数应用(整数a)
{
返回Math.abs(a);
}
})));
// ...
创建另一个(更务实的)答案,以区分两种方法(参见Kevin Day的评论):

这可以在一个数组过程中完成(排序为O(log n)),而无需创建任何新列表。只需不使用Collections.max。只需在运行过程中计算绝对值,并运行最小值/最大值:

List<Integer> l = Arrays.asList(3, -5, -7, 10, -2, 4);
int iterMin = Integer.MAX_VALUE;
for(Integer i : l)
  if(Math.abs(i) < iterMin)
    iterMin = Math.abs(i);
List l=Arrays.asList(3,-5,-7,10,-2,4);
int iterMin=整数最大值;
for(整数i:l)
if(数学abs(i)
如果要保留原始值,可以轻松执行以下操作:

int iterMinOrig = Integer.MAX_VALUE;
for(Integer i : l)
  if(Math.abs(i) < Math.abs(iterMinOrig))
    iterMinOrig = i;
int iterminig=Integer.MAX\u值;
for(整数i:l)
if(数学abs(i)
我建议使用比较器。例如,如果您的列表是双倍的,则您有以下选项:

获取最大绝对值:

double maxAbs = Collections.max( myList, new Comparator<Double>() {
        @Override
        public int compare(Double x, Double y) {
            return Math.abs(x) < Math.abs(y) ? -1 : 1;
        }

    });
double-maxAbs=Collections.max(myList,new-Comparator(){
@凌驾
公共整数比较(双x,双y){
返回数学abs(x)<数学abs(y)?-1:1;
}
});
获取最小绝对值:

double minAbs = Collections.max( myList, new Comparator<Double>() {
        @Override
        public int compare(Double x, Double y) {
            return Math.abs(x) > Math.abs(y) ? -1 : 1;
        }

    });
double minAbs=Collections.max(myList,new Comparator(){
@凌驾
公共整数比较(双x,双y){
返回Math.abs(x)>Math.abs(y)?-1:1;
}
});
按升序排列列表(相对于绝对值):

Collections.sort(myList,newcomparator(){
@凌驾
公共整数比较(双x,双y){
返回数学abs(x)<数学abs(y)?-1:1;
}
});
按降序排列列表(相对于绝对值):

Collections.sort(myList,newcomparator(){
@凌驾
公共整数比较(双x,双y){
返回Math.abs(x)>Math.abs(y)?-1:1;
}
});

如果您有其他类型,如整数,只需将python中的Double替换为Integer,不需要lambda,只需映射(abs,…)就行了……睡眠剥夺再次造成了损失。java无法足够快地获取闭包。啊,好吧。我被迫创建一个临时列表。如果这太迂腐,我深表歉意,但不会“返回Collections.max(x);”只返回列表中的最大值?对。我没有看到“最小值”
double maxAbs = Collections.max( myList, new Comparator<Double>() {
        @Override
        public int compare(Double x, Double y) {
            return Math.abs(x) < Math.abs(y) ? -1 : 1;
        }

    });
double minAbs = Collections.max( myList, new Comparator<Double>() {
        @Override
        public int compare(Double x, Double y) {
            return Math.abs(x) > Math.abs(y) ? -1 : 1;
        }

    });
Collections.sort( myList, new Comparator<Double>() {
            @Override
            public int compare(Double x, Double y) {
                return Math.abs(x) < Math.abs(y) ? -1 : 1;
            }

        });
Collections.sort( myList, new Comparator<Double>() {
            @Override
            public int compare(Double x, Double y) {
                return Math.abs(x) > Math.abs(y) ? -1 : 1;
            }

        });