Categories
discuss

Java stream collect counting to field

Is it possible use Collectors.groupingBy() with Collectors.counting() to count to the field of a custom object instead of creating a map and transforming it afterwards.

I have a list of users, like this:

public class User {
    private String firstName;
    private String lastName;
    // some more attributes

    // getters and setters
}

I want to count all users with the same first and last name. Therefore I have custom object looking like this:

public static class NameGroup {
    private String firstName;
    private String lastName;
    private long count;

    // getters and setters
}

I can collect the name groups using this:

List<NameGroup> names = users.stream()
        .collect(Collectors.groupingBy(p -> Arrays.asList(p.getFirstName(), p.getLastName()), Collectors.counting()))
        .entrySet().stream()
        .map(e -> new NameGroup(e.getKey().get(0), e.getKey().get(1), e.getValue()))
        .collect(Collectors.toList());

With this solution I have to group the users first to a map and transform it afterwards to my custom object. Is it possible to count all names directly to nameGroup.count to avoid iterating twice over the list (or map) and improve the performance?

Answer

You can minimize allocations of intermediate objects, e.g. all the Arrays.asList(...) objects, by build a map yourself, instead of using streaming.

This relies on the fact that your NameGroup is mutable.

To even make the code simpler, lets add two helpers to NameGroup:

public static class NameGroup {
    // fields here

    public NameGroup(User user) {
        this.firstName = user.getFirstName();
        this.lastName = user.getLastName();
    }

    public void incrementCount() {
        this.count++;
    }

    // other constructors, getters and setters here
}

With that in place, you can implement the logic like this:

Map<User, NameGroup> map = new TreeMap<>(Comparator.comparing(User::getFirstName)
                                                   .thenComparing(User::getLastName));
users.stream().forEach(user -> map.computeIfAbsent(user, NameGroup::new).incrementCount());
List<NameGroup> names = new ArrayList<>(map.values());

Or if you don’t actually need a list, the last line can be simplified to:

Collection<NameGroup> names = map.values();
Categories
discuss

Does Axios have the ability to detect redirects?

The Response interface of the Fetch API has a read-only flag, redirected, which indicates whether or not the response was the result of a request that was redirected.

Does the axios library have a similar capability? The best I could find is maxRedirects which sets the maximum number of redirects to follow. However, I am simply looking to determine if it happened or not (so I can handle redirects specially), not prevent it from happening.

Answer

Compare the request URL from your code with the URL given by response.request.responseURL; if those aren’t equal, you know the request was redirected.

As far as the status code being 200, that’s what’s required by the spec; no intermediate status codes are exposed to frontend JavaScript running in a browser — regardless of which API you use. See also the answer at http://stackoverflow.com/a/46031800/441757

Categories
discuss

What is cb in multer?

In the code below, from the multer API, both the destination and filename options are anonymous functions. Both of these functions have an argument called cb. Are these callback functions defined in the multer module somewhere or am I supposed to supply them?

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/tmp/my-uploads')
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }
})

var upload = multer({ storage: storage }

Answer

The answer is: yes cb is provided by multer. And yes, it’s weird documentation says nothing about it.

This callback is a so called error-first function, thus when examining the req, or file you may decide, that user uploaded something wrong, pass new Error() as first argument, and it will be returned in response. Note though, that it will raise an unhandled exception in your app. So I prefer to always pass null and handle user input in the corresponding controller.

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    const error = file.mimetype === 'image/jpeg'
      ? null
      : new Error('wrong file');
    cb(error, '/if-no-error-upload-file-to-this-directory');
  },
  //same for filename
});
Categories
discuss

Using Deferred<...> in Room DAO with Kotlin Coroutines

I’m trying to use Coroutines with a Room database in an Android project. I’ve found almost no documentation online, and I’m wondering if it is possible to return Deferred<> types in those methods. Something like this:

@Dao
interface MyObjectDAO {

@Query("SELECT * FROM myObject WHERE id_myObject = :idMyObject")
suspend fun readMyObjectAsync(idMyObject: Int): Deferred<MyObject>
}

I’ve tried this and I get Not sure how to convert a Cursor to this method's return type at compile time.

My dependencies are:

kapt 'androidx.room:room-compiler:2.1.0-alpha04'
implementation 'androidx.room:room-runtime:2.1.0-alpha04'
implementation 'androidx.room:room-coroutines:2.1.0-alpha04'

Answer

Your issue lies in that you’re mixing the suspending converter and the Deferred converter. Use one or the other and your code will work as intended.

  • fun readMyObjectAsync(idMyObject: Int): Deferred<MyObject> – Best choice if you need to interface/be compatible with java code, since it doesn’t require code transformations to actually function.
  • suspend fun readMyObjectAsync(idMyObject: Int): MyObject – If you’re operating on pure kotlin this will allow better control through the context it is called in.
Categories
discuss

EnumSet.copyOf empty collection throws IllegalArgumentException

I have below code which fails with IllegalArgumentException

public EnumSet<test> getData(){  // Line 1
   return EnumSet.copyOf(get(test))) // Line 2
}



private Collection<Test> get(Test[] test){  //Line 1
 test= test==null ? new Test[0] : test;     // line 2
 return Array.asList(test) //Line 3
}

if test is null , then line 2 of get function creates empty array of Test and EnumSet.copyOf(get(test)) throws IllegalArgumentException

I dont understand why this exception is thrown ?

Answer

An EnumSet uses some reflection to identify the type of its elements. (The set uses the “ordinal” of the enum values to track whether each element is included or not.)

When you create an EnumSet with copyOf(Collection), it checks to see if the collection is an EnumSet. If it is, it uses the same type as the source set. Otherwise, it attempts to call getClass() on the first element in the source collection. If the collection is empty, there is no first element, and nothing to query for its class. So it fails in that case (“throws IllegalArgumentException if c is not an EnumSet instance and contains no elements”).

To create an empty EnumSet, you need to determine the class yourself, and use noneOf().

Collection<Test> tests = get(test);
return tests.isEmpty() ? EnumSet.noneOf(Test.class) : EnumSet.copyOf(tests);
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..