如何将此程序转换为使用流的Java 8功能样式? [英] How do I convert this program into java 8 functional style using streams?

查看:93
本文介绍了如何将此程序转换为使用流的Java 8功能样式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我已经编写了一个程序来查找给定字符串的字符的大写和小写的每种可能性。



一个例子是
Input - ab/Ab等 - 任何一个
输出 - [ab,Ab,aB, AB]



代码



错误的算法 -

  public static ArrayList< String> permuteUCLC(String a)
{

String s = new String(a.toLowerCase());
ArrayList< String> arr = new ArrayList<>();
arr.add(a);
int l = a.length();
for(int i = 0; i <= 1; i ++)
{
for(int j = i + 1; j< = 1; j ++)
{
arr.add(s.substring(0,i)+ s.substring(i,j).toUpperCase()+ s.substring(j,l));
}
}
Collections.sort(arr);
Collections.reverse(arr);
return arr;

code


$ b

注意

在提出这个问题后,我意识到我的算法是错误的。我会在适当的时候尝试上传正确的算法。




子代码(正确代码)
这是用于查找所有子序列并将它们上限的代码。假设所有字符都是唯一的。如何找到索引
并以函数方式实现它?

  public static void permuteSubsequence(String a)
{
int n = a.length();
for(int i = 0; i <(1 {
String buff =; (((1 {$($)$
为(int j = 0; j }
else
{
buff = buff + a.charAt(j);
}
}
System.out.println(buff);
}
}

从上述案例中挑选指数。即1和它们的大写索引。




请求



如何使用Java流将上面的代码转换为功能样式?



我正面临的问题是模拟map方法中的索引范围。
另外,是否有一种方法可以生成字符串流,以将相同的字符串复制到所有元素中,类似于 IntStream.range(a,b)

  public static List< String> permuteStreams(String a)
{
int l =(int)(Math.pow(2,a.length()) - 1)
ArrayList< String> al = new ArrayList<>();
for(int i = 0; i< = 1; i ++)
al.add(a); //生成一个流并将其复制回arraylist,如果可能的话?

列表< String> sl = al.stream()
.map()//不完整的代码
.collect(Collectors.toList());
返回sl;


解决方案

不排列字符串分裂和加入他们,这是一个相当昂贵的操作,完全没有必要。考虑到大写和小写恰好是两种状态,并且排列两个状态项的组合应该响起,我们正在讨论 二进制数字 。计算机中的整数是比特的组合,具有两种状态,并且遍历这些比特的所有可能的排列与遍历整数范围一样简单。

即,范围 0,1,2,3,4,5,6,7 的二进制数表示是 000,001,010,011, 100,101,110,111 。现在,假设 0 代表小写, 1 代表三个字符的字符串大写,而您'

所以剩下的任务是根据字符串的字符大小写转换为大写或小写。到相关位是否被设置。有几种方法可以实现这一点。以下代码创建一个初始小写字符串作为所有迭代的起点,并将字符切换为大写,如果设置了一些:

  public static void permuteSubsequence(String s){
if(s.isEmpty()){
System.out.println();
return;
}
字符串lower = s.toLowerCase(),upper = s.toUpperCase();
if(s.length()!= lower.length()|| s.length()!= upper.length())
抛出新的UnsupportedOperationException(非平凡大小写映射);
LongStream.range(0,1L<< Math.min(lower.length(),62))
.mapToObj(l - > {
StringBuilder sb = new StringBuilder(lower );
BitSet.valueOf(new long [] {l})。stream()
.forEach(ix - > sb.setCharAt(ix,upper.charAt(ix)));
return sb.toString();
})
.forEach(System.out :: println);

$ / code>

请注意,此实现仅通过对第一个 62 长字符串的字符,因为用于迭代的带符号的 long 不允许更多,但是排列 62 字符已经允许 4611686018427387904 组合,所以即使我们假设打印一个变体只需要一纳秒,我们也需要超过一百年才能将它们全部打印出来。所以你永远不会注意到作弊。



字符串的大写/小写转换不必产生长度相同的字符串。此实现将拒绝具有非平凡大小写映射的字符串,对此,这种排列是不可能的。



要改进的一件事是,忽略没有的字符一个不同的大写和小写形式。这可以通过首先标识置换字符(它们的位置)并仅置换这些字符来完成:

  public static void permuteSubsequence(String s){
int [] permutable = IntStream.range(0,s.length())
.filter(i-> Character.toLowerCase(s.charAt(i))!= Character。 toUpperCase(s.charAt(i)))
.toArray();
if(permutable.length == 0){
System.out.println(s);
return;
}
字符串lower = s.toLowerCase(),upper = s.toUpperCase();
if(s.length()!= lower.length()|| s.length()!= upper.length())
抛出新的UnsupportedOperationException(非平凡大小写映射);
LongStream.range(0,1L<< Math.min(permutable.length,62))
.mapToObj(1 - > {
StringBuilder sb = new StringBuilder(lower);
BitSet.valueOf(new long [] {l})。stream()
.map(bit - >> permutable [bit])
.forEach(ix - > sb.setCharAt (ix,upper.charAt(ix)));
return sb.toString();
})
.forEach(System.out :: println);

$ / code>

借此, permuteSubsequence(Mr.X ); will print

  mr.x 
Mr .x
mR.x
MR.x
mr.X
Mr.X
mR.X
MR.X


Problem
I have written a program to find out every possibility of Uppercase and Lowercase of a character for a given string.

An example would be, Input - "ab"/"Ab" etc. -- any one of those Output - ["ab","Ab","aB","AB"]

Code

Incorrect algorithm - please check below.

public static ArrayList<String> permuteUCLC(String a)
{

    String s=new String(a.toLowerCase());
    ArrayList<String> arr = new ArrayList<>();
    arr.add(a);
    int l = a.length();
    for(int i=0;i<=l;i++)
    {
        for(int j=i+1;j<=l;j++)
        {
            arr.add(s.substring(0,i)+s.substring(i,j).toUpperCase()+s.substring(j,l));
        }
    }
    Collections.sort(arr);
    Collections.reverse(arr);
    return arr;
}


Caution
I have realized after asking the question that my algorithm is wrong. I will try and upload correct algorithm in due course.


Subsequence Code (Correct Code) This is the code for finding all sub-sequences and upper-casing them. Assuming that all characters are unique. How to find the indices and implement it in functional way?

public static void permuteSubsequence(String a)
{
    int n=a.length();
    for(int i=0;i<(1<<n);i++)
    {
        String buff="";
        for(int j=0;j<n;j++)
        {
            if(((1<<j)&i)!=0) 
            {
                buff=buff+new Character(a.charAt(j)).toString().toUpperCase();
            }
            else
            {
                buff = buff + a.charAt(j);
            }
        }
        System.out.println(buff);
    }
}

Pick up the indices from the above case. i.e., the indices of 1's and uppercase them.


Request

How to convert the above code into functional style using Java streams?

The problem I am facing is simulating indices range in the map method. Also, is there a way to generate Strings's Stream for copying same string into all elements, something similar to IntStream.range(a,b)?

public static List<String> permuteStreams(String a)
{
    int l=(int)(Math.pow(2,a.length())-1)
    ArrayList<String> al = new ArrayList<>();
    for(int i=0;i<=l;i++)
        al.add(a);//Generate a stream and copy back into arraylist maybe if possible?

    List<String> sl = al.stream()
      .map()//incomplete code
      .collect(Collectors.toList());
    return sl;
}

解决方案

Don’t permutate strings by splitting and joining them, that is quite an expensive operation and completely unnecessary. Consider that "uppercase" and "lowercase" are exactly two states and permuting combinations of two-state items should ring a bell, we’re talking about binary numbers. Integer numbers in a computer are combinations of bits, having two states, and iterating through all possible permutations of these bits is as easy as iterating through an integer number range.

I.e. the binary number representation of the range 0, 1, 2, 3, 4, 5, 6, 7 is 000, 001, 010, 011, 100, 101, 110, 111. Now imagine 0 to stand for "lowercase" and 1 to stand for "uppercase" for a three character string and you’re almost done.

So the remaining task is to turn the characters of a String to uppercase or lowercase according to whether the associated bit is set or not. There are several ways to achieve this. The following code creates an initially lowercase string as starting point of all iterations and toggles the characters to uppercase, if a bit is set:

public static void permuteSubsequence(String s) {
    if(s.isEmpty()) {
        System.out.println();
        return;
    }
    String lower = s.toLowerCase(), upper = s.toUpperCase();
    if(s.length()!=lower.length() || s.length()!=upper.length())
        throw new UnsupportedOperationException("non trivial case mapping");
    LongStream.range(0, 1L<<Math.min(lower.length(), 62))
        .mapToObj(l -> {
            StringBuilder sb=new StringBuilder(lower);
            BitSet.valueOf(new long[] { l }).stream()
                  .forEach(ix -> sb.setCharAt(ix, upper.charAt(ix)));
            return sb.toString();
        })
        .forEach(System.out::println);
}

Note that this implementation cheats by only permuting the first 62 characters of longer strings, as the signed long used for iterating doesn’t allow more, but permuting 62 characters already allows 4611686018427387904 combinations, so even if we assume that printing one variant takes only one nanosecond, we would need way more than hundred years to print them all. So you’ll never notice the cheating.

A uppercase/lowercase conversion of a string doesn’t have to produce a string of the same length. This implementation will reject strings with nontrivial case mapping, for which this kind of permutation is not possible.

One thing to improve, is to leave out characters that don’t have a different uppercase and lowercase form. This can be done by identifying the permutable characters (their positions) first and permute only these characters:

public static void permuteSubsequence(String s) {
    int[] permutable = IntStream.range(0, s.length())
        .filter(i->Character.toLowerCase(s.charAt(i))!=Character.toUpperCase(s.charAt(i)))
        .toArray();
    if(permutable.length == 0) {
        System.out.println(s);
        return;
    }
    String lower = s.toLowerCase(), upper = s.toUpperCase();
    if(s.length()!=lower.length() || s.length()!=upper.length())
        throw new UnsupportedOperationException("non trivial case mapping");
    LongStream.range(0, 1L<<Math.min(permutable.length, 62))
        .mapToObj(l -> {
            StringBuilder sb=new StringBuilder(lower);
            BitSet.valueOf(new long[] { l }).stream()
                  .map(bit -> permutable[bit])
                  .forEach(ix -> sb.setCharAt(ix, upper.charAt(ix)));
            return sb.toString();
        })
        .forEach(System.out::println);
}

With this, permuteSubsequence("Mr.X"); will print

mr.x
Mr.x
mR.x
MR.x
mr.X
Mr.X
mR.X
MR.X

这篇关于如何将此程序转换为使用流的Java 8功能样式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆